1f06ca4afSHartmut Brandt /*
2f06ca4afSHartmut Brandt * Copyright (c) 2001-2003
3f06ca4afSHartmut Brandt * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4f06ca4afSHartmut Brandt * All rights reserved.
5f06ca4afSHartmut Brandt *
6f06ca4afSHartmut Brandt * Author: Harti Brandt <harti@freebsd.org>
7f06ca4afSHartmut Brandt *
8135f7de5SShteryana Shopova * Copyright (c) 2010 The FreeBSD Foundation
9135f7de5SShteryana Shopova * All rights reserved.
10135f7de5SShteryana Shopova *
11135f7de5SShteryana Shopova * Portions of this software were developed by Shteryana Sotirova Shopova
12135f7de5SShteryana Shopova * under sponsorship from the FreeBSD Foundation.
13135f7de5SShteryana Shopova *
14896052c1SHartmut Brandt * Redistribution and use in source and binary forms, with or without
15896052c1SHartmut Brandt * modification, are permitted provided that the following conditions
16896052c1SHartmut Brandt * are met:
17896052c1SHartmut Brandt * 1. Redistributions of source code must retain the above copyright
18896052c1SHartmut Brandt * notice, this list of conditions and the following disclaimer.
19f06ca4afSHartmut Brandt * 2. Redistributions in binary form must reproduce the above copyright
20f06ca4afSHartmut Brandt * notice, this list of conditions and the following disclaimer in the
21f06ca4afSHartmut Brandt * documentation and/or other materials provided with the distribution.
22f06ca4afSHartmut Brandt *
23896052c1SHartmut Brandt * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24896052c1SHartmut Brandt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25896052c1SHartmut Brandt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26896052c1SHartmut Brandt * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
27896052c1SHartmut Brandt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28896052c1SHartmut Brandt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29896052c1SHartmut Brandt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30896052c1SHartmut Brandt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31896052c1SHartmut Brandt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32896052c1SHartmut Brandt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33896052c1SHartmut Brandt * SUCH DAMAGE.
34f06ca4afSHartmut Brandt *
35165c5d31SHartmut Brandt * $Begemot: bsnmp/lib/snmp.c,v 1.40 2005/10/04 14:32:42 brandt_h Exp $
36f06ca4afSHartmut Brandt *
37f06ca4afSHartmut Brandt * SNMP
38f06ca4afSHartmut Brandt */
39f06ca4afSHartmut Brandt #include <sys/types.h>
40f06ca4afSHartmut Brandt #include <sys/socket.h>
4184615743SEnji Cooper #include <ctype.h>
4284615743SEnji Cooper #include <errno.h>
4384615743SEnji Cooper #include <netdb.h>
44f06ca4afSHartmut Brandt #include <stdio.h>
45f06ca4afSHartmut Brandt #include <stdlib.h>
46f06ca4afSHartmut Brandt #include <stddef.h>
47f06ca4afSHartmut Brandt #include <stdarg.h>
4884615743SEnji Cooper #include <string.h>
49165c5d31SHartmut Brandt #ifdef HAVE_STDINT_H
50896052c1SHartmut Brandt #include <stdint.h>
51165c5d31SHartmut Brandt #elif defined(HAVE_INTTYPES_H)
52165c5d31SHartmut Brandt #include <inttypes.h>
53165c5d31SHartmut Brandt #endif
546521e5f8SEnji Cooper #include <netinet/in.h>
556521e5f8SEnji Cooper #include <arpa/inet.h>
56f06ca4afSHartmut Brandt
57f06ca4afSHartmut Brandt #include "asn1.h"
58f06ca4afSHartmut Brandt #include "snmp.h"
59f06ca4afSHartmut Brandt #include "snmppriv.h"
60f06ca4afSHartmut Brandt
61f06ca4afSHartmut Brandt static void snmp_error_func(const char *, ...);
62f06ca4afSHartmut Brandt static void snmp_printf_func(const char *, ...);
63f06ca4afSHartmut Brandt
64f06ca4afSHartmut Brandt void (*snmp_error)(const char *, ...) = snmp_error_func;
65f06ca4afSHartmut Brandt void (*snmp_printf)(const char *, ...) = snmp_printf_func;
66f06ca4afSHartmut Brandt
67f06ca4afSHartmut Brandt /*
68f06ca4afSHartmut Brandt * Get the next variable binding from the list.
69f06ca4afSHartmut Brandt * ASN errors on the sequence or the OID are always fatal.
70f06ca4afSHartmut Brandt */
71f06ca4afSHartmut Brandt static enum asn_err
get_var_binding(struct asn_buf * b,struct snmp_value * binding)72f06ca4afSHartmut Brandt get_var_binding(struct asn_buf *b, struct snmp_value *binding)
73f06ca4afSHartmut Brandt {
74f06ca4afSHartmut Brandt u_char type;
75f06ca4afSHartmut Brandt asn_len_t len, trailer;
76f06ca4afSHartmut Brandt enum asn_err err;
77f06ca4afSHartmut Brandt
78f06ca4afSHartmut Brandt if (asn_get_sequence(b, &len) != ASN_ERR_OK) {
79f06ca4afSHartmut Brandt snmp_error("cannot parse varbind header");
80f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
81f06ca4afSHartmut Brandt }
82f06ca4afSHartmut Brandt
83f06ca4afSHartmut Brandt /* temporary truncate the length so that the parser does not
84f06ca4afSHartmut Brandt * eat up bytes behind the sequence in the case the encoding is
85f06ca4afSHartmut Brandt * wrong of inner elements. */
86f06ca4afSHartmut Brandt trailer = b->asn_len - len;
87f06ca4afSHartmut Brandt b->asn_len = len;
88f06ca4afSHartmut Brandt
89f06ca4afSHartmut Brandt if (asn_get_objid(b, &binding->var) != ASN_ERR_OK) {
90f06ca4afSHartmut Brandt snmp_error("cannot parse binding objid");
91f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
92f06ca4afSHartmut Brandt }
93f06ca4afSHartmut Brandt if (asn_get_header(b, &type, &len) != ASN_ERR_OK) {
94f06ca4afSHartmut Brandt snmp_error("cannot parse binding value header");
95f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
96f06ca4afSHartmut Brandt }
97f06ca4afSHartmut Brandt
98f06ca4afSHartmut Brandt switch (type) {
99f06ca4afSHartmut Brandt
100f06ca4afSHartmut Brandt case ASN_TYPE_NULL:
101f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_NULL;
102f06ca4afSHartmut Brandt err = asn_get_null_raw(b, len);
103f06ca4afSHartmut Brandt break;
104f06ca4afSHartmut Brandt
105f06ca4afSHartmut Brandt case ASN_TYPE_INTEGER:
106f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_INTEGER;
107f06ca4afSHartmut Brandt err = asn_get_integer_raw(b, len, &binding->v.integer);
108f06ca4afSHartmut Brandt break;
109f06ca4afSHartmut Brandt
110f06ca4afSHartmut Brandt case ASN_TYPE_OCTETSTRING:
111f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_OCTETSTRING;
112f06ca4afSHartmut Brandt binding->v.octetstring.octets = malloc(len);
113f06ca4afSHartmut Brandt if (binding->v.octetstring.octets == NULL) {
114f06ca4afSHartmut Brandt snmp_error("%s", strerror(errno));
115f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
116f06ca4afSHartmut Brandt }
117f06ca4afSHartmut Brandt binding->v.octetstring.len = len;
118f06ca4afSHartmut Brandt err = asn_get_octetstring_raw(b, len,
119f06ca4afSHartmut Brandt binding->v.octetstring.octets,
120f06ca4afSHartmut Brandt &binding->v.octetstring.len);
121f06ca4afSHartmut Brandt if (ASN_ERR_STOPPED(err)) {
122f06ca4afSHartmut Brandt free(binding->v.octetstring.octets);
123f06ca4afSHartmut Brandt binding->v.octetstring.octets = NULL;
124f06ca4afSHartmut Brandt }
125f06ca4afSHartmut Brandt break;
126f06ca4afSHartmut Brandt
127f06ca4afSHartmut Brandt case ASN_TYPE_OBJID:
128f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_OID;
129f06ca4afSHartmut Brandt err = asn_get_objid_raw(b, len, &binding->v.oid);
130f06ca4afSHartmut Brandt break;
131f06ca4afSHartmut Brandt
132f06ca4afSHartmut Brandt case ASN_CLASS_APPLICATION|ASN_APP_IPADDRESS:
133f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_IPADDRESS;
134f06ca4afSHartmut Brandt err = asn_get_ipaddress_raw(b, len, binding->v.ipaddress);
135f06ca4afSHartmut Brandt break;
136f06ca4afSHartmut Brandt
137f06ca4afSHartmut Brandt case ASN_CLASS_APPLICATION|ASN_APP_TIMETICKS:
138f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_TIMETICKS;
139f06ca4afSHartmut Brandt err = asn_get_uint32_raw(b, len, &binding->v.uint32);
140f06ca4afSHartmut Brandt break;
141f06ca4afSHartmut Brandt
142f06ca4afSHartmut Brandt case ASN_CLASS_APPLICATION|ASN_APP_COUNTER:
143f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_COUNTER;
144f06ca4afSHartmut Brandt err = asn_get_uint32_raw(b, len, &binding->v.uint32);
145f06ca4afSHartmut Brandt break;
146f06ca4afSHartmut Brandt
147f06ca4afSHartmut Brandt case ASN_CLASS_APPLICATION|ASN_APP_GAUGE:
148f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_GAUGE;
149f06ca4afSHartmut Brandt err = asn_get_uint32_raw(b, len, &binding->v.uint32);
150f06ca4afSHartmut Brandt break;
151f06ca4afSHartmut Brandt
152f06ca4afSHartmut Brandt case ASN_CLASS_APPLICATION|ASN_APP_COUNTER64:
153f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_COUNTER64;
154f06ca4afSHartmut Brandt err = asn_get_counter64_raw(b, len, &binding->v.counter64);
155f06ca4afSHartmut Brandt break;
156f06ca4afSHartmut Brandt
157f06ca4afSHartmut Brandt case ASN_CLASS_CONTEXT | ASN_EXCEPT_NOSUCHOBJECT:
158f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_NOSUCHOBJECT;
159f06ca4afSHartmut Brandt err = asn_get_null_raw(b, len);
160f06ca4afSHartmut Brandt break;
161f06ca4afSHartmut Brandt
162f06ca4afSHartmut Brandt case ASN_CLASS_CONTEXT | ASN_EXCEPT_NOSUCHINSTANCE:
163f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_NOSUCHINSTANCE;
164f06ca4afSHartmut Brandt err = asn_get_null_raw(b, len);
165f06ca4afSHartmut Brandt break;
166f06ca4afSHartmut Brandt
167f06ca4afSHartmut Brandt case ASN_CLASS_CONTEXT | ASN_EXCEPT_ENDOFMIBVIEW:
168f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_ENDOFMIBVIEW;
169f06ca4afSHartmut Brandt err = asn_get_null_raw(b, len);
170f06ca4afSHartmut Brandt break;
171f06ca4afSHartmut Brandt
172f06ca4afSHartmut Brandt default:
173f06ca4afSHartmut Brandt if ((err = asn_skip(b, len)) == ASN_ERR_OK)
174f06ca4afSHartmut Brandt err = ASN_ERR_TAG;
175f06ca4afSHartmut Brandt snmp_error("bad binding value type 0x%x", type);
176f06ca4afSHartmut Brandt break;
177f06ca4afSHartmut Brandt }
178f06ca4afSHartmut Brandt
179f06ca4afSHartmut Brandt if (ASN_ERR_STOPPED(err)) {
180f06ca4afSHartmut Brandt snmp_error("cannot parse binding value");
181f06ca4afSHartmut Brandt return (err);
182f06ca4afSHartmut Brandt }
183f06ca4afSHartmut Brandt
184f06ca4afSHartmut Brandt if (b->asn_len != 0)
185f06ca4afSHartmut Brandt snmp_error("ignoring junk at end of binding");
186f06ca4afSHartmut Brandt
187f06ca4afSHartmut Brandt b->asn_len = trailer;
188f06ca4afSHartmut Brandt
189f06ca4afSHartmut Brandt return (err);
190f06ca4afSHartmut Brandt }
191f06ca4afSHartmut Brandt
192f06ca4afSHartmut Brandt /*
193f06ca4afSHartmut Brandt * Parse the different PDUs contents. Any ASN error in the outer components
194f06ca4afSHartmut Brandt * are fatal. Only errors in variable values may be tolerated. If all
195f06ca4afSHartmut Brandt * components can be parsed it returns either ASN_ERR_OK or the first
196f06ca4afSHartmut Brandt * error that was found.
197f06ca4afSHartmut Brandt */
198f06ca4afSHartmut Brandt enum asn_err
snmp_parse_pdus_hdr(struct asn_buf * b,struct snmp_pdu * pdu,asn_len_t * lenp)199f06ca4afSHartmut Brandt snmp_parse_pdus_hdr(struct asn_buf *b, struct snmp_pdu *pdu, asn_len_t *lenp)
200f06ca4afSHartmut Brandt {
201f06ca4afSHartmut Brandt if (pdu->type == SNMP_PDU_TRAP) {
202f06ca4afSHartmut Brandt if (asn_get_objid(b, &pdu->enterprise) != ASN_ERR_OK) {
203f06ca4afSHartmut Brandt snmp_error("cannot parse trap enterprise");
204f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
205f06ca4afSHartmut Brandt }
206f06ca4afSHartmut Brandt if (asn_get_ipaddress(b, pdu->agent_addr) != ASN_ERR_OK) {
207f06ca4afSHartmut Brandt snmp_error("cannot parse trap agent address");
208f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
209f06ca4afSHartmut Brandt }
210f06ca4afSHartmut Brandt if (asn_get_integer(b, &pdu->generic_trap) != ASN_ERR_OK) {
211f06ca4afSHartmut Brandt snmp_error("cannot parse 'generic-trap'");
212f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
213f06ca4afSHartmut Brandt }
214f06ca4afSHartmut Brandt if (asn_get_integer(b, &pdu->specific_trap) != ASN_ERR_OK) {
215f06ca4afSHartmut Brandt snmp_error("cannot parse 'specific-trap'");
216f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
217f06ca4afSHartmut Brandt }
218f06ca4afSHartmut Brandt if (asn_get_timeticks(b, &pdu->time_stamp) != ASN_ERR_OK) {
219f06ca4afSHartmut Brandt snmp_error("cannot parse trap 'time-stamp'");
220f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
221f06ca4afSHartmut Brandt }
222f06ca4afSHartmut Brandt } else {
223f06ca4afSHartmut Brandt if (asn_get_integer(b, &pdu->request_id) != ASN_ERR_OK) {
224f06ca4afSHartmut Brandt snmp_error("cannot parse 'request-id'");
225f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
226f06ca4afSHartmut Brandt }
227f06ca4afSHartmut Brandt if (asn_get_integer(b, &pdu->error_status) != ASN_ERR_OK) {
228f06ca4afSHartmut Brandt snmp_error("cannot parse 'error_status'");
229f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
230f06ca4afSHartmut Brandt }
231f06ca4afSHartmut Brandt if (asn_get_integer(b, &pdu->error_index) != ASN_ERR_OK) {
232f06ca4afSHartmut Brandt snmp_error("cannot parse 'error_index'");
233f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
234f06ca4afSHartmut Brandt }
235f06ca4afSHartmut Brandt }
236f06ca4afSHartmut Brandt
237f06ca4afSHartmut Brandt if (asn_get_sequence(b, lenp) != ASN_ERR_OK) {
238f06ca4afSHartmut Brandt snmp_error("cannot get varlist header");
239f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
240f06ca4afSHartmut Brandt }
241f06ca4afSHartmut Brandt
242f06ca4afSHartmut Brandt return (ASN_ERR_OK);
243f06ca4afSHartmut Brandt }
244f06ca4afSHartmut Brandt
245f06ca4afSHartmut Brandt static enum asn_err
parse_pdus(struct asn_buf * b,struct snmp_pdu * pdu,int32_t * ip)246f06ca4afSHartmut Brandt parse_pdus(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip)
247f06ca4afSHartmut Brandt {
248f06ca4afSHartmut Brandt asn_len_t len, trailer;
249f06ca4afSHartmut Brandt struct snmp_value *v;
250f06ca4afSHartmut Brandt enum asn_err err, err1;
251f06ca4afSHartmut Brandt
252f06ca4afSHartmut Brandt err = snmp_parse_pdus_hdr(b, pdu, &len);
253f06ca4afSHartmut Brandt if (ASN_ERR_STOPPED(err))
254f06ca4afSHartmut Brandt return (err);
255f06ca4afSHartmut Brandt
256f06ca4afSHartmut Brandt trailer = b->asn_len - len;
257f06ca4afSHartmut Brandt
258f06ca4afSHartmut Brandt v = pdu->bindings;
259f06ca4afSHartmut Brandt err = ASN_ERR_OK;
260f06ca4afSHartmut Brandt while (b->asn_len != 0) {
261f06ca4afSHartmut Brandt if (pdu->nbindings == SNMP_MAX_BINDINGS) {
262f06ca4afSHartmut Brandt snmp_error("too many bindings (> %u) in PDU",
263f06ca4afSHartmut Brandt SNMP_MAX_BINDINGS);
264f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
265f06ca4afSHartmut Brandt }
266f06ca4afSHartmut Brandt err1 = get_var_binding(b, v);
267f06ca4afSHartmut Brandt if (ASN_ERR_STOPPED(err1))
268f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
269f06ca4afSHartmut Brandt if (err1 != ASN_ERR_OK && err == ASN_ERR_OK) {
270f06ca4afSHartmut Brandt err = err1;
271f06ca4afSHartmut Brandt *ip = pdu->nbindings + 1;
272f06ca4afSHartmut Brandt }
273f06ca4afSHartmut Brandt pdu->nbindings++;
274f06ca4afSHartmut Brandt v++;
275f06ca4afSHartmut Brandt }
276f06ca4afSHartmut Brandt
277f06ca4afSHartmut Brandt b->asn_len = trailer;
278f06ca4afSHartmut Brandt
279f06ca4afSHartmut Brandt return (err);
280f06ca4afSHartmut Brandt }
281f06ca4afSHartmut Brandt
282135f7de5SShteryana Shopova
283135f7de5SShteryana Shopova static enum asn_err
parse_secparams(struct asn_buf * b,struct snmp_pdu * pdu)284135f7de5SShteryana Shopova parse_secparams(struct asn_buf *b, struct snmp_pdu *pdu)
285f06ca4afSHartmut Brandt {
286135f7de5SShteryana Shopova asn_len_t octs_len;
287135f7de5SShteryana Shopova u_char buf[256]; /* XXX: calc max possible size here */
288135f7de5SShteryana Shopova struct asn_buf tb;
289f06ca4afSHartmut Brandt
290135f7de5SShteryana Shopova memset(buf, 0, 256);
291135f7de5SShteryana Shopova tb.asn_ptr = buf;
292135f7de5SShteryana Shopova tb.asn_len = 256;
2931108712cSShteryana Shopova u_int len = 256;
294135f7de5SShteryana Shopova
29506983448SShteryana Shopova if (asn_get_octetstring(b, buf, &len) != ASN_ERR_OK) {
296135f7de5SShteryana Shopova snmp_error("cannot parse usm header");
297f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
298f06ca4afSHartmut Brandt }
29906983448SShteryana Shopova tb.asn_len = len;
300f06ca4afSHartmut Brandt
301135f7de5SShteryana Shopova if (asn_get_sequence(&tb, &octs_len) != ASN_ERR_OK) {
302135f7de5SShteryana Shopova snmp_error("cannot decode usm header");
303f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
304f06ca4afSHartmut Brandt }
305f06ca4afSHartmut Brandt
306135f7de5SShteryana Shopova octs_len = SNMP_ENGINE_ID_SIZ;
307135f7de5SShteryana Shopova if (asn_get_octetstring(&tb, (u_char *)&pdu->engine.engine_id,
308135f7de5SShteryana Shopova &octs_len) != ASN_ERR_OK) {
309135f7de5SShteryana Shopova snmp_error("cannot decode msg engine id");
310f06ca4afSHartmut Brandt return (ASN_ERR_FAILED);
311f06ca4afSHartmut Brandt }
312135f7de5SShteryana Shopova pdu->engine.engine_len = octs_len;
313135f7de5SShteryana Shopova
314135f7de5SShteryana Shopova if (asn_get_integer(&tb, &pdu->engine.engine_boots) != ASN_ERR_OK) {
315135f7de5SShteryana Shopova snmp_error("cannot decode msg engine boots");
316135f7de5SShteryana Shopova return (ASN_ERR_FAILED);
317135f7de5SShteryana Shopova }
318135f7de5SShteryana Shopova
319135f7de5SShteryana Shopova if (asn_get_integer(&tb, &pdu->engine.engine_time) != ASN_ERR_OK) {
320135f7de5SShteryana Shopova snmp_error("cannot decode msg engine time");
321135f7de5SShteryana Shopova return (ASN_ERR_FAILED);
322135f7de5SShteryana Shopova }
323135f7de5SShteryana Shopova
324135f7de5SShteryana Shopova octs_len = SNMP_ADM_STR32_SIZ - 1;
325135f7de5SShteryana Shopova if (asn_get_octetstring(&tb, (u_char *)&pdu->user.sec_name, &octs_len)
326135f7de5SShteryana Shopova != ASN_ERR_OK) {
327135f7de5SShteryana Shopova snmp_error("cannot decode msg user name");
328135f7de5SShteryana Shopova return (ASN_ERR_FAILED);
329135f7de5SShteryana Shopova }
330135f7de5SShteryana Shopova pdu->user.sec_name[octs_len] = '\0';
331135f7de5SShteryana Shopova
332135f7de5SShteryana Shopova octs_len = sizeof(pdu->msg_digest);
333135f7de5SShteryana Shopova if (asn_get_octetstring(&tb, (u_char *)&pdu->msg_digest, &octs_len) !=
334135f7de5SShteryana Shopova ASN_ERR_OK || ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0 &&
335135f7de5SShteryana Shopova octs_len != sizeof(pdu->msg_digest))) {
336135f7de5SShteryana Shopova snmp_error("cannot decode msg authentication param");
337135f7de5SShteryana Shopova return (ASN_ERR_FAILED);
338135f7de5SShteryana Shopova }
339135f7de5SShteryana Shopova
340135f7de5SShteryana Shopova octs_len = sizeof(pdu->msg_salt);
341135f7de5SShteryana Shopova if (asn_get_octetstring(&tb, (u_char *)&pdu->msg_salt, &octs_len) !=
342135f7de5SShteryana Shopova ASN_ERR_OK ||((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0 &&
343135f7de5SShteryana Shopova octs_len != sizeof(pdu->msg_salt))) {
344135f7de5SShteryana Shopova snmp_error("cannot decode msg authentication param");
345135f7de5SShteryana Shopova return (ASN_ERR_FAILED);
346135f7de5SShteryana Shopova }
347135f7de5SShteryana Shopova
348135f7de5SShteryana Shopova if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) {
349135f7de5SShteryana Shopova pdu->digest_ptr = b->asn_ptr - SNMP_USM_AUTH_SIZE;
350135f7de5SShteryana Shopova pdu->digest_ptr -= octs_len + ASN_MAXLENLEN;
351135f7de5SShteryana Shopova }
352f06ca4afSHartmut Brandt
353f06ca4afSHartmut Brandt return (ASN_ERR_OK);
354f06ca4afSHartmut Brandt }
355f06ca4afSHartmut Brandt
356135f7de5SShteryana Shopova static enum snmp_code
pdu_encode_secparams(struct asn_buf * b,struct snmp_pdu * pdu)357135f7de5SShteryana Shopova pdu_encode_secparams(struct asn_buf *b, struct snmp_pdu *pdu)
358f06ca4afSHartmut Brandt {
359135f7de5SShteryana Shopova u_char buf[256], *sptr;
360135f7de5SShteryana Shopova struct asn_buf tb;
361135f7de5SShteryana Shopova size_t auth_off, moved = 0;
362f06ca4afSHartmut Brandt
363135f7de5SShteryana Shopova auth_off = 0;
364135f7de5SShteryana Shopova memset(buf, 0, 256);
365135f7de5SShteryana Shopova tb.asn_ptr = buf;
366135f7de5SShteryana Shopova tb.asn_len = 256;
367f06ca4afSHartmut Brandt
368135f7de5SShteryana Shopova if (asn_put_temp_header(&tb, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED),
369135f7de5SShteryana Shopova &sptr) != ASN_ERR_OK)
370135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
371f06ca4afSHartmut Brandt
372135f7de5SShteryana Shopova if (asn_put_octetstring(&tb, (u_char *)pdu->engine.engine_id,
373135f7de5SShteryana Shopova pdu->engine.engine_len) != ASN_ERR_OK)
374135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
375f06ca4afSHartmut Brandt
376135f7de5SShteryana Shopova if (asn_put_integer(&tb, pdu->engine.engine_boots) != ASN_ERR_OK)
377135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
378f06ca4afSHartmut Brandt
379135f7de5SShteryana Shopova if (asn_put_integer(&tb, pdu->engine.engine_time) != ASN_ERR_OK)
380135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
381f06ca4afSHartmut Brandt
382135f7de5SShteryana Shopova if (asn_put_octetstring(&tb, (u_char *)pdu->user.sec_name,
383135f7de5SShteryana Shopova strlen(pdu->user.sec_name)) != ASN_ERR_OK)
384135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
385135f7de5SShteryana Shopova
386135f7de5SShteryana Shopova if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) {
387135f7de5SShteryana Shopova auth_off = sizeof(buf) - tb.asn_len + ASN_MAXLENLEN;
388135f7de5SShteryana Shopova if (asn_put_octetstring(&tb, (u_char *)pdu->msg_digest,
389135f7de5SShteryana Shopova sizeof(pdu->msg_digest)) != ASN_ERR_OK)
390135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
391135f7de5SShteryana Shopova } else {
392135f7de5SShteryana Shopova if (asn_put_octetstring(&tb, (u_char *)pdu->msg_digest, 0)
393135f7de5SShteryana Shopova != ASN_ERR_OK)
394135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
395135f7de5SShteryana Shopova }
396135f7de5SShteryana Shopova
397135f7de5SShteryana Shopova if ((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0) {
398135f7de5SShteryana Shopova if (asn_put_octetstring(&tb, (u_char *)pdu->msg_salt,
399135f7de5SShteryana Shopova sizeof(pdu->msg_salt)) != ASN_ERR_OK)
400135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
401135f7de5SShteryana Shopova } else {
402135f7de5SShteryana Shopova if (asn_put_octetstring(&tb, (u_char *)pdu->msg_salt, 0)
403135f7de5SShteryana Shopova != ASN_ERR_OK)
404135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
405135f7de5SShteryana Shopova }
406135f7de5SShteryana Shopova
407135f7de5SShteryana Shopova if (asn_commit_header(&tb, sptr, &moved) != ASN_ERR_OK)
408135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
409135f7de5SShteryana Shopova
410135f7de5SShteryana Shopova if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0)
411135f7de5SShteryana Shopova pdu->digest_ptr = b->asn_ptr + auth_off - moved;
412135f7de5SShteryana Shopova
413135f7de5SShteryana Shopova if (asn_put_octetstring(b, buf, sizeof(buf) - tb.asn_len) != ASN_ERR_OK)
414135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
415135f7de5SShteryana Shopova pdu->digest_ptr += ASN_MAXLENLEN;
416135f7de5SShteryana Shopova
417135f7de5SShteryana Shopova if ((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0 && asn_put_temp_header(b,
418135f7de5SShteryana Shopova ASN_TYPE_OCTETSTRING, &pdu->encrypted_ptr) != ASN_ERR_OK)
419135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
420135f7de5SShteryana Shopova
421135f7de5SShteryana Shopova return (SNMP_CODE_OK);
422f06ca4afSHartmut Brandt }
423f06ca4afSHartmut Brandt
424f06ca4afSHartmut Brandt /*
425f06ca4afSHartmut Brandt * Decode the PDU except for the variable bindings itself.
426f06ca4afSHartmut Brandt * If decoding fails because of a bad binding, but the rest can be
427f06ca4afSHartmut Brandt * decoded, ip points to the index of the failed variable (errors
428f06ca4afSHartmut Brandt * OORANGE, BADLEN or BADVERS).
429f06ca4afSHartmut Brandt */
430f06ca4afSHartmut Brandt enum snmp_code
snmp_pdu_decode(struct asn_buf * b,struct snmp_pdu * pdu,int32_t * ip)431f06ca4afSHartmut Brandt snmp_pdu_decode(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip)
432f06ca4afSHartmut Brandt {
433135f7de5SShteryana Shopova enum snmp_code code;
434135f7de5SShteryana Shopova
435135f7de5SShteryana Shopova if ((code = snmp_pdu_decode_header(b, pdu)) != SNMP_CODE_OK)
436135f7de5SShteryana Shopova return (code);
437135f7de5SShteryana Shopova
438135f7de5SShteryana Shopova if (pdu->version == SNMP_V3) {
439135f7de5SShteryana Shopova if (pdu->security_model != SNMP_SECMODEL_USM)
440135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
441135f7de5SShteryana Shopova if ((code = snmp_pdu_decode_secmode(b, pdu)) != SNMP_CODE_OK)
442135f7de5SShteryana Shopova return (code);
443135f7de5SShteryana Shopova }
444135f7de5SShteryana Shopova
445135f7de5SShteryana Shopova code = snmp_pdu_decode_scoped(b, pdu, ip);
446135f7de5SShteryana Shopova
447135f7de5SShteryana Shopova switch (code) {
448135f7de5SShteryana Shopova case SNMP_CODE_FAILED:
449135f7de5SShteryana Shopova snmp_pdu_free(pdu);
450135f7de5SShteryana Shopova break;
451135f7de5SShteryana Shopova
452135f7de5SShteryana Shopova case SNMP_CODE_BADENC:
453135f7de5SShteryana Shopova if (pdu->version == SNMP_Verr)
454135f7de5SShteryana Shopova return (SNMP_CODE_BADVERS);
455135f7de5SShteryana Shopova
456135f7de5SShteryana Shopova default:
457135f7de5SShteryana Shopova break;
458135f7de5SShteryana Shopova }
459135f7de5SShteryana Shopova
460135f7de5SShteryana Shopova return (code);
461135f7de5SShteryana Shopova }
462135f7de5SShteryana Shopova
463135f7de5SShteryana Shopova enum snmp_code
snmp_pdu_decode_header(struct asn_buf * b,struct snmp_pdu * pdu)464135f7de5SShteryana Shopova snmp_pdu_decode_header(struct asn_buf *b, struct snmp_pdu *pdu)
465135f7de5SShteryana Shopova {
466135f7de5SShteryana Shopova int32_t version;
467135f7de5SShteryana Shopova u_int octs_len;
468f06ca4afSHartmut Brandt asn_len_t len;
469f06ca4afSHartmut Brandt
470135f7de5SShteryana Shopova pdu->outer_ptr = b->asn_ptr;
471135f7de5SShteryana Shopova pdu->outer_len = b->asn_len;
472f06ca4afSHartmut Brandt
473f06ca4afSHartmut Brandt if (asn_get_sequence(b, &len) != ASN_ERR_OK) {
474f06ca4afSHartmut Brandt snmp_error("cannot decode pdu header");
475f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED);
476f06ca4afSHartmut Brandt }
477f06ca4afSHartmut Brandt if (b->asn_len < len) {
478f06ca4afSHartmut Brandt snmp_error("outer sequence value too short");
479f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED);
480f06ca4afSHartmut Brandt }
481f06ca4afSHartmut Brandt if (b->asn_len != len) {
482f06ca4afSHartmut Brandt snmp_error("ignoring trailing junk in message");
483f06ca4afSHartmut Brandt b->asn_len = len;
484f06ca4afSHartmut Brandt }
485f06ca4afSHartmut Brandt
486135f7de5SShteryana Shopova if (asn_get_integer(b, &version) != ASN_ERR_OK) {
487135f7de5SShteryana Shopova snmp_error("cannot decode version");
488f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED);
489135f7de5SShteryana Shopova }
490f06ca4afSHartmut Brandt
491135f7de5SShteryana Shopova if (version == 0)
492135f7de5SShteryana Shopova pdu->version = SNMP_V1;
493135f7de5SShteryana Shopova else if (version == 1)
494135f7de5SShteryana Shopova pdu->version = SNMP_V2c;
495135f7de5SShteryana Shopova else if (version == 3)
496135f7de5SShteryana Shopova pdu->version = SNMP_V3;
497135f7de5SShteryana Shopova else {
498135f7de5SShteryana Shopova pdu->version = SNMP_Verr;
499135f7de5SShteryana Shopova snmp_error("unsupported SNMP version");
500f06ca4afSHartmut Brandt return (SNMP_CODE_BADENC);
501f06ca4afSHartmut Brandt }
502f06ca4afSHartmut Brandt
503135f7de5SShteryana Shopova if (pdu->version == SNMP_V3) {
504135f7de5SShteryana Shopova if (asn_get_sequence(b, &len) != ASN_ERR_OK) {
505135f7de5SShteryana Shopova snmp_error("cannot decode pdu global data header");
506135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
507135f7de5SShteryana Shopova }
508135f7de5SShteryana Shopova
509135f7de5SShteryana Shopova if (asn_get_integer(b, &pdu->identifier) != ASN_ERR_OK) {
510135f7de5SShteryana Shopova snmp_error("cannot decode msg indetifier");
511135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
512135f7de5SShteryana Shopova }
513135f7de5SShteryana Shopova
514135f7de5SShteryana Shopova if (asn_get_integer(b, &pdu->engine.max_msg_size)
515135f7de5SShteryana Shopova != ASN_ERR_OK) {
516135f7de5SShteryana Shopova snmp_error("cannot decode msg size");
517135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
518135f7de5SShteryana Shopova }
519135f7de5SShteryana Shopova
520135f7de5SShteryana Shopova octs_len = 1;
521135f7de5SShteryana Shopova if (asn_get_octetstring(b, (u_char *)&pdu->flags,
522135f7de5SShteryana Shopova &octs_len) != ASN_ERR_OK) {
523135f7de5SShteryana Shopova snmp_error("cannot decode msg flags");
524135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
525135f7de5SShteryana Shopova }
526135f7de5SShteryana Shopova
527135f7de5SShteryana Shopova if (asn_get_integer(b, &pdu->security_model) != ASN_ERR_OK) {
528135f7de5SShteryana Shopova snmp_error("cannot decode msg size");
529135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
530135f7de5SShteryana Shopova }
531135f7de5SShteryana Shopova
532135f7de5SShteryana Shopova if (pdu->security_model != SNMP_SECMODEL_USM)
533135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
534135f7de5SShteryana Shopova
535135f7de5SShteryana Shopova if (parse_secparams(b, pdu) != ASN_ERR_OK)
536135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
537135f7de5SShteryana Shopova } else {
538135f7de5SShteryana Shopova octs_len = SNMP_COMMUNITY_MAXLEN;
539135f7de5SShteryana Shopova if (asn_get_octetstring(b, (u_char *)pdu->community,
540135f7de5SShteryana Shopova &octs_len) != ASN_ERR_OK) {
541135f7de5SShteryana Shopova snmp_error("cannot decode community");
542135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
543135f7de5SShteryana Shopova }
544135f7de5SShteryana Shopova pdu->community[octs_len] = '\0';
545135f7de5SShteryana Shopova }
546135f7de5SShteryana Shopova
547f06ca4afSHartmut Brandt return (SNMP_CODE_OK);
548f06ca4afSHartmut Brandt }
549f06ca4afSHartmut Brandt
550135f7de5SShteryana Shopova enum snmp_code
snmp_pdu_decode_scoped(struct asn_buf * b,struct snmp_pdu * pdu,int32_t * ip)551135f7de5SShteryana Shopova snmp_pdu_decode_scoped(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip)
552135f7de5SShteryana Shopova {
553135f7de5SShteryana Shopova u_char type;
554135f7de5SShteryana Shopova asn_len_t len, trailer;
555135f7de5SShteryana Shopova enum asn_err err;
556135f7de5SShteryana Shopova
557135f7de5SShteryana Shopova if (pdu->version == SNMP_V3) {
558135f7de5SShteryana Shopova if (asn_get_sequence(b, &len) != ASN_ERR_OK) {
559135f7de5SShteryana Shopova snmp_error("cannot decode scoped pdu header");
560135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
561135f7de5SShteryana Shopova }
562135f7de5SShteryana Shopova
563135f7de5SShteryana Shopova len = SNMP_ENGINE_ID_SIZ;
564135f7de5SShteryana Shopova if (asn_get_octetstring(b, (u_char *)&pdu->context_engine,
565135f7de5SShteryana Shopova &len) != ASN_ERR_OK) {
566135f7de5SShteryana Shopova snmp_error("cannot decode msg context engine");
567135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
568135f7de5SShteryana Shopova }
569135f7de5SShteryana Shopova pdu->context_engine_len = len;
570135f7de5SShteryana Shopova
571135f7de5SShteryana Shopova len = SNMP_CONTEXT_NAME_SIZ;
572135f7de5SShteryana Shopova if (asn_get_octetstring(b, (u_char *)&pdu->context_name,
573135f7de5SShteryana Shopova &len) != ASN_ERR_OK) {
574135f7de5SShteryana Shopova snmp_error("cannot decode msg context name");
575135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
576135f7de5SShteryana Shopova }
577135f7de5SShteryana Shopova pdu->context_name[len] = '\0';
578135f7de5SShteryana Shopova }
579135f7de5SShteryana Shopova
580135f7de5SShteryana Shopova if (asn_get_header(b, &type, &len) != ASN_ERR_OK) {
581135f7de5SShteryana Shopova snmp_error("cannot get pdu header");
582135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
583135f7de5SShteryana Shopova }
584135f7de5SShteryana Shopova if ((type & ~ASN_TYPE_MASK) !=
585135f7de5SShteryana Shopova (ASN_TYPE_CONSTRUCTED | ASN_CLASS_CONTEXT)) {
586135f7de5SShteryana Shopova snmp_error("bad pdu header tag");
587135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
588135f7de5SShteryana Shopova }
589135f7de5SShteryana Shopova pdu->type = type & ASN_TYPE_MASK;
590135f7de5SShteryana Shopova
591135f7de5SShteryana Shopova switch (pdu->type) {
592135f7de5SShteryana Shopova
593135f7de5SShteryana Shopova case SNMP_PDU_GET:
594135f7de5SShteryana Shopova case SNMP_PDU_GETNEXT:
595135f7de5SShteryana Shopova case SNMP_PDU_RESPONSE:
596135f7de5SShteryana Shopova case SNMP_PDU_SET:
597135f7de5SShteryana Shopova break;
598135f7de5SShteryana Shopova
599135f7de5SShteryana Shopova case SNMP_PDU_TRAP:
600135f7de5SShteryana Shopova if (pdu->version != SNMP_V1) {
601135f7de5SShteryana Shopova snmp_error("bad pdu type %u", pdu->type);
602135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
603135f7de5SShteryana Shopova }
604135f7de5SShteryana Shopova break;
605135f7de5SShteryana Shopova
606135f7de5SShteryana Shopova case SNMP_PDU_GETBULK:
607135f7de5SShteryana Shopova case SNMP_PDU_INFORM:
608135f7de5SShteryana Shopova case SNMP_PDU_TRAP2:
609135f7de5SShteryana Shopova case SNMP_PDU_REPORT:
610135f7de5SShteryana Shopova if (pdu->version == SNMP_V1) {
611135f7de5SShteryana Shopova snmp_error("bad pdu type %u", pdu->type);
612135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
613135f7de5SShteryana Shopova }
614135f7de5SShteryana Shopova break;
615135f7de5SShteryana Shopova
616135f7de5SShteryana Shopova default:
617135f7de5SShteryana Shopova snmp_error("bad pdu type %u", pdu->type);
618135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
619135f7de5SShteryana Shopova }
620135f7de5SShteryana Shopova
621135f7de5SShteryana Shopova trailer = b->asn_len - len;
622135f7de5SShteryana Shopova b->asn_len = len;
623135f7de5SShteryana Shopova
624135f7de5SShteryana Shopova err = parse_pdus(b, pdu, ip);
625135f7de5SShteryana Shopova if (ASN_ERR_STOPPED(err))
626135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
627135f7de5SShteryana Shopova
628135f7de5SShteryana Shopova if (b->asn_len != 0)
629135f7de5SShteryana Shopova snmp_error("ignoring trailing junk after pdu");
630135f7de5SShteryana Shopova
631135f7de5SShteryana Shopova b->asn_len = trailer;
632135f7de5SShteryana Shopova
633135f7de5SShteryana Shopova return (SNMP_CODE_OK);
634135f7de5SShteryana Shopova }
635135f7de5SShteryana Shopova
636135f7de5SShteryana Shopova enum snmp_code
snmp_pdu_decode_secmode(struct asn_buf * b,struct snmp_pdu * pdu)637135f7de5SShteryana Shopova snmp_pdu_decode_secmode(struct asn_buf *b, struct snmp_pdu *pdu)
638135f7de5SShteryana Shopova {
639135f7de5SShteryana Shopova u_char type;
640135f7de5SShteryana Shopova enum snmp_code code;
641135f7de5SShteryana Shopova uint8_t digest[SNMP_USM_AUTH_SIZE];
642135f7de5SShteryana Shopova
643135f7de5SShteryana Shopova if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH &&
644135f7de5SShteryana Shopova (pdu->flags & SNMP_MSG_AUTH_FLAG) == 0)
645135f7de5SShteryana Shopova return (SNMP_CODE_BADSECLEVEL);
646135f7de5SShteryana Shopova
6472b802662SShteryana Shopova if ((code = snmp_pdu_calc_digest(pdu, digest)) !=
648135f7de5SShteryana Shopova SNMP_CODE_OK)
649135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
650135f7de5SShteryana Shopova
651135f7de5SShteryana Shopova if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH &&
652135f7de5SShteryana Shopova memcmp(digest, pdu->msg_digest, sizeof(pdu->msg_digest)) != 0)
653135f7de5SShteryana Shopova return (SNMP_CODE_BADDIGEST);
654135f7de5SShteryana Shopova
655135f7de5SShteryana Shopova if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV && (asn_get_header(b, &type,
656135f7de5SShteryana Shopova &pdu->scoped_len) != ASN_ERR_OK || type != ASN_TYPE_OCTETSTRING)) {
657135f7de5SShteryana Shopova snmp_error("cannot decode encrypted pdu");
658135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
659135f7de5SShteryana Shopova }
660135f7de5SShteryana Shopova pdu->scoped_ptr = b->asn_ptr;
661135f7de5SShteryana Shopova
662135f7de5SShteryana Shopova if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV &&
663135f7de5SShteryana Shopova (pdu->flags & SNMP_MSG_PRIV_FLAG) == 0)
664135f7de5SShteryana Shopova return (SNMP_CODE_BADSECLEVEL);
665135f7de5SShteryana Shopova
6662b802662SShteryana Shopova if ((code = snmp_pdu_decrypt(pdu)) != SNMP_CODE_OK)
667135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
668135f7de5SShteryana Shopova
669135f7de5SShteryana Shopova return (code);
670135f7de5SShteryana Shopova }
671135f7de5SShteryana Shopova
672f06ca4afSHartmut Brandt /*
67370af00a1SHartmut Brandt * Check whether what we have is the complete PDU by snooping at the
67470af00a1SHartmut Brandt * enclosing structure header. This returns:
67570af00a1SHartmut Brandt * -1 if there are ASN.1 errors
67670af00a1SHartmut Brandt * 0 if we need more data
67770af00a1SHartmut Brandt * > 0 the length of this PDU
67870af00a1SHartmut Brandt */
67970af00a1SHartmut Brandt int
snmp_pdu_snoop(const struct asn_buf * b0)68070af00a1SHartmut Brandt snmp_pdu_snoop(const struct asn_buf *b0)
68170af00a1SHartmut Brandt {
68270af00a1SHartmut Brandt u_int length;
68370af00a1SHartmut Brandt asn_len_t len;
68470af00a1SHartmut Brandt struct asn_buf b = *b0;
68570af00a1SHartmut Brandt
68670af00a1SHartmut Brandt /* <0x10|0x20> <len> <data...> */
68770af00a1SHartmut Brandt
68870af00a1SHartmut Brandt if (b.asn_len == 0)
68970af00a1SHartmut Brandt return (0);
69070af00a1SHartmut Brandt if (b.asn_cptr[0] != (ASN_TYPE_SEQUENCE | ASN_TYPE_CONSTRUCTED)) {
69170af00a1SHartmut Brandt asn_error(&b, "bad sequence type %u", b.asn_cptr[0]);
69270af00a1SHartmut Brandt return (-1);
69370af00a1SHartmut Brandt }
69470af00a1SHartmut Brandt b.asn_len--;
69570af00a1SHartmut Brandt b.asn_cptr++;
69670af00a1SHartmut Brandt
69770af00a1SHartmut Brandt if (b.asn_len == 0)
69870af00a1SHartmut Brandt return (0);
69970af00a1SHartmut Brandt
70070af00a1SHartmut Brandt if (*b.asn_cptr & 0x80) {
70170af00a1SHartmut Brandt /* long length */
70270af00a1SHartmut Brandt length = *b.asn_cptr++ & 0x7f;
70370af00a1SHartmut Brandt b.asn_len--;
70470af00a1SHartmut Brandt if (length == 0) {
70570af00a1SHartmut Brandt asn_error(&b, "indefinite length not supported");
70670af00a1SHartmut Brandt return (-1);
70770af00a1SHartmut Brandt }
70870af00a1SHartmut Brandt if (length > ASN_MAXLENLEN) {
70970af00a1SHartmut Brandt asn_error(&b, "long length too long (%u)", length);
71070af00a1SHartmut Brandt return (-1);
71170af00a1SHartmut Brandt }
71270af00a1SHartmut Brandt if (length > b.asn_len)
71370af00a1SHartmut Brandt return (0);
71470af00a1SHartmut Brandt len = 0;
71570af00a1SHartmut Brandt while (length--) {
71670af00a1SHartmut Brandt len = (len << 8) | *b.asn_cptr++;
71770af00a1SHartmut Brandt b.asn_len--;
71870af00a1SHartmut Brandt }
71970af00a1SHartmut Brandt } else {
72070af00a1SHartmut Brandt len = *b.asn_cptr++;
72170af00a1SHartmut Brandt b.asn_len--;
72270af00a1SHartmut Brandt }
72370af00a1SHartmut Brandt
72470af00a1SHartmut Brandt if (len > b.asn_len)
72570af00a1SHartmut Brandt return (0);
72670af00a1SHartmut Brandt
72770af00a1SHartmut Brandt return (len + b.asn_cptr - b0->asn_cptr);
72870af00a1SHartmut Brandt }
72970af00a1SHartmut Brandt
73070af00a1SHartmut Brandt /*
731f06ca4afSHartmut Brandt * Encode the SNMP PDU without the variable bindings field.
732f06ca4afSHartmut Brandt * We do this the rather uneffective way by
733f06ca4afSHartmut Brandt * moving things around and assuming that the length field will never
734f06ca4afSHartmut Brandt * use more than 2 bytes.
735f06ca4afSHartmut Brandt * We need a number of pointers to apply the fixes afterwards.
736f06ca4afSHartmut Brandt */
737f06ca4afSHartmut Brandt enum snmp_code
snmp_pdu_encode_header(struct asn_buf * b,struct snmp_pdu * pdu)738f06ca4afSHartmut Brandt snmp_pdu_encode_header(struct asn_buf *b, struct snmp_pdu *pdu)
739f06ca4afSHartmut Brandt {
740f06ca4afSHartmut Brandt enum asn_err err;
741135f7de5SShteryana Shopova u_char *v3_hdr_ptr;
742f06ca4afSHartmut Brandt
743f06ca4afSHartmut Brandt if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED),
744f06ca4afSHartmut Brandt &pdu->outer_ptr) != ASN_ERR_OK)
745f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED);
746f06ca4afSHartmut Brandt
747f06ca4afSHartmut Brandt if (pdu->version == SNMP_V1)
748f06ca4afSHartmut Brandt err = asn_put_integer(b, 0);
749f06ca4afSHartmut Brandt else if (pdu->version == SNMP_V2c)
750f06ca4afSHartmut Brandt err = asn_put_integer(b, 1);
751135f7de5SShteryana Shopova else if (pdu->version == SNMP_V3)
752135f7de5SShteryana Shopova err = asn_put_integer(b, 3);
753f06ca4afSHartmut Brandt else
754f06ca4afSHartmut Brandt return (SNMP_CODE_BADVERS);
755f06ca4afSHartmut Brandt if (err != ASN_ERR_OK)
756f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED);
757f06ca4afSHartmut Brandt
758135f7de5SShteryana Shopova if (pdu->version == SNMP_V3) {
759135f7de5SShteryana Shopova if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE |
760135f7de5SShteryana Shopova ASN_TYPE_CONSTRUCTED), &v3_hdr_ptr) != ASN_ERR_OK)
761135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
762135f7de5SShteryana Shopova
763135f7de5SShteryana Shopova if (asn_put_integer(b, pdu->identifier) != ASN_ERR_OK)
764135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
765135f7de5SShteryana Shopova
766135f7de5SShteryana Shopova if (asn_put_integer(b, pdu->engine.max_msg_size) != ASN_ERR_OK)
767135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
768135f7de5SShteryana Shopova
769135f7de5SShteryana Shopova if (pdu->type != SNMP_PDU_RESPONSE &&
770135f7de5SShteryana Shopova pdu->type != SNMP_PDU_TRAP &&
77172cd7a52SShteryana Shopova pdu->type != SNMP_PDU_TRAP2 &&
772135f7de5SShteryana Shopova pdu->type != SNMP_PDU_REPORT)
773135f7de5SShteryana Shopova pdu->flags |= SNMP_MSG_REPORT_FLAG;
774135f7de5SShteryana Shopova
775135f7de5SShteryana Shopova if (asn_put_octetstring(b, (u_char *)&pdu->flags, 1)
776135f7de5SShteryana Shopova != ASN_ERR_OK)
777135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
778135f7de5SShteryana Shopova
779135f7de5SShteryana Shopova if (asn_put_integer(b, pdu->security_model) != ASN_ERR_OK)
780135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
781135f7de5SShteryana Shopova
782135f7de5SShteryana Shopova if (asn_commit_header(b, v3_hdr_ptr, NULL) != ASN_ERR_OK)
783135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
784135f7de5SShteryana Shopova
785135f7de5SShteryana Shopova if (pdu->security_model != SNMP_SECMODEL_USM)
786135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
787135f7de5SShteryana Shopova
788135f7de5SShteryana Shopova if (pdu_encode_secparams(b, pdu) != SNMP_CODE_OK)
789135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
790135f7de5SShteryana Shopova
791135f7de5SShteryana Shopova /* View-based Access Conntrol information */
792135f7de5SShteryana Shopova if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE |
793135f7de5SShteryana Shopova ASN_TYPE_CONSTRUCTED), &pdu->scoped_ptr) != ASN_ERR_OK)
794135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
795135f7de5SShteryana Shopova
796135f7de5SShteryana Shopova if (asn_put_octetstring(b, (u_char *)pdu->context_engine,
797135f7de5SShteryana Shopova pdu->context_engine_len) != ASN_ERR_OK)
798135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
799135f7de5SShteryana Shopova
800135f7de5SShteryana Shopova if (asn_put_octetstring(b, (u_char *)pdu->context_name,
801135f7de5SShteryana Shopova strlen(pdu->context_name)) != ASN_ERR_OK)
802135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
803135f7de5SShteryana Shopova } else {
804f06ca4afSHartmut Brandt if (asn_put_octetstring(b, (u_char *)pdu->community,
805f06ca4afSHartmut Brandt strlen(pdu->community)) != ASN_ERR_OK)
806f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED);
807135f7de5SShteryana Shopova }
808f06ca4afSHartmut Brandt
809f06ca4afSHartmut Brandt if (asn_put_temp_header(b, (ASN_TYPE_CONSTRUCTED | ASN_CLASS_CONTEXT |
810f06ca4afSHartmut Brandt pdu->type), &pdu->pdu_ptr) != ASN_ERR_OK)
811f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED);
812f06ca4afSHartmut Brandt
813f06ca4afSHartmut Brandt if (pdu->type == SNMP_PDU_TRAP) {
814f06ca4afSHartmut Brandt if (pdu->version != SNMP_V1 ||
815f06ca4afSHartmut Brandt asn_put_objid(b, &pdu->enterprise) != ASN_ERR_OK ||
816f06ca4afSHartmut Brandt asn_put_ipaddress(b, pdu->agent_addr) != ASN_ERR_OK ||
817f06ca4afSHartmut Brandt asn_put_integer(b, pdu->generic_trap) != ASN_ERR_OK ||
818f06ca4afSHartmut Brandt asn_put_integer(b, pdu->specific_trap) != ASN_ERR_OK ||
819f06ca4afSHartmut Brandt asn_put_timeticks(b, pdu->time_stamp) != ASN_ERR_OK)
820f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED);
821f06ca4afSHartmut Brandt } else {
822f06ca4afSHartmut Brandt if (pdu->version == SNMP_V1 && (pdu->type == SNMP_PDU_GETBULK ||
823f06ca4afSHartmut Brandt pdu->type == SNMP_PDU_INFORM ||
824f06ca4afSHartmut Brandt pdu->type == SNMP_PDU_TRAP2 ||
825f06ca4afSHartmut Brandt pdu->type == SNMP_PDU_REPORT))
826f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED);
827f06ca4afSHartmut Brandt
828f06ca4afSHartmut Brandt if (asn_put_integer(b, pdu->request_id) != ASN_ERR_OK ||
829f06ca4afSHartmut Brandt asn_put_integer(b, pdu->error_status) != ASN_ERR_OK ||
830f06ca4afSHartmut Brandt asn_put_integer(b, pdu->error_index) != ASN_ERR_OK)
831f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED);
832f06ca4afSHartmut Brandt }
833f06ca4afSHartmut Brandt
834f06ca4afSHartmut Brandt if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED),
835f06ca4afSHartmut Brandt &pdu->vars_ptr) != ASN_ERR_OK)
836f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED);
837f06ca4afSHartmut Brandt
838f06ca4afSHartmut Brandt return (SNMP_CODE_OK);
839f06ca4afSHartmut Brandt }
840f06ca4afSHartmut Brandt
841135f7de5SShteryana Shopova static enum asn_err
snmp_pdu_fix_padd(struct asn_buf * b,struct snmp_pdu * pdu)842135f7de5SShteryana Shopova snmp_pdu_fix_padd(struct asn_buf *b, struct snmp_pdu *pdu)
843f06ca4afSHartmut Brandt {
844135f7de5SShteryana Shopova asn_len_t padlen;
845135f7de5SShteryana Shopova
846135f7de5SShteryana Shopova if (pdu->user.priv_proto == SNMP_PRIV_DES && pdu->scoped_len % 8 != 0) {
847135f7de5SShteryana Shopova padlen = 8 - (pdu->scoped_len % 8);
848135f7de5SShteryana Shopova if (asn_pad(b, padlen) != ASN_ERR_OK)
849135f7de5SShteryana Shopova return (ASN_ERR_FAILED);
850135f7de5SShteryana Shopova pdu->scoped_len += padlen;
851135f7de5SShteryana Shopova }
852135f7de5SShteryana Shopova
853135f7de5SShteryana Shopova return (ASN_ERR_OK);
854135f7de5SShteryana Shopova }
855135f7de5SShteryana Shopova
856135f7de5SShteryana Shopova enum snmp_code
snmp_fix_encoding(struct asn_buf * b,struct snmp_pdu * pdu)857135f7de5SShteryana Shopova snmp_fix_encoding(struct asn_buf *b, struct snmp_pdu *pdu)
858135f7de5SShteryana Shopova {
859135f7de5SShteryana Shopova size_t moved = 0;
860135f7de5SShteryana Shopova enum snmp_code code;
861135f7de5SShteryana Shopova
862135f7de5SShteryana Shopova if (asn_commit_header(b, pdu->vars_ptr, NULL) != ASN_ERR_OK ||
863135f7de5SShteryana Shopova asn_commit_header(b, pdu->pdu_ptr, NULL) != ASN_ERR_OK)
864f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED);
865135f7de5SShteryana Shopova
866135f7de5SShteryana Shopova if (pdu->version == SNMP_V3) {
867135f7de5SShteryana Shopova if (asn_commit_header(b, pdu->scoped_ptr, NULL) != ASN_ERR_OK)
868135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
869135f7de5SShteryana Shopova
870135f7de5SShteryana Shopova pdu->scoped_len = b->asn_ptr - pdu->scoped_ptr;
87106983448SShteryana Shopova if (snmp_pdu_fix_padd(b, pdu) != ASN_ERR_OK)
872135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
873135f7de5SShteryana Shopova
874135f7de5SShteryana Shopova if (pdu->security_model != SNMP_SECMODEL_USM)
875135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
876135f7de5SShteryana Shopova
8772b802662SShteryana Shopova if (snmp_pdu_encrypt(pdu) != SNMP_CODE_OK)
878135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
879135f7de5SShteryana Shopova
880135f7de5SShteryana Shopova if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV &&
881135f7de5SShteryana Shopova asn_commit_header(b, pdu->encrypted_ptr, NULL) != ASN_ERR_OK)
882135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
883135f7de5SShteryana Shopova }
884135f7de5SShteryana Shopova
885135f7de5SShteryana Shopova if (asn_commit_header(b, pdu->outer_ptr, &moved) != ASN_ERR_OK)
886135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
887135f7de5SShteryana Shopova
888135f7de5SShteryana Shopova pdu->outer_len = b->asn_ptr - pdu->outer_ptr;
889135f7de5SShteryana Shopova pdu->digest_ptr -= moved;
890135f7de5SShteryana Shopova
891135f7de5SShteryana Shopova if (pdu->version == SNMP_V3) {
8922b802662SShteryana Shopova if ((code = snmp_pdu_calc_digest(pdu, pdu->msg_digest)) !=
893135f7de5SShteryana Shopova SNMP_CODE_OK)
894135f7de5SShteryana Shopova return (SNMP_CODE_FAILED);
895135f7de5SShteryana Shopova
896135f7de5SShteryana Shopova if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0)
897135f7de5SShteryana Shopova memcpy(pdu->digest_ptr, pdu->msg_digest,
898135f7de5SShteryana Shopova sizeof(pdu->msg_digest));
899135f7de5SShteryana Shopova }
900135f7de5SShteryana Shopova
901f06ca4afSHartmut Brandt return (SNMP_CODE_OK);
902f06ca4afSHartmut Brandt }
903f06ca4afSHartmut Brandt
904f06ca4afSHartmut Brandt /*
905f06ca4afSHartmut Brandt * Encode a binding. Caller must ensure, that the syntax is ok for that version.
906f06ca4afSHartmut Brandt * Be sure not to cobber b, when something fails.
907f06ca4afSHartmut Brandt */
908f06ca4afSHartmut Brandt enum asn_err
snmp_binding_encode(struct asn_buf * b,const struct snmp_value * binding)909f06ca4afSHartmut Brandt snmp_binding_encode(struct asn_buf *b, const struct snmp_value *binding)
910f06ca4afSHartmut Brandt {
911f06ca4afSHartmut Brandt u_char *ptr;
912f06ca4afSHartmut Brandt enum asn_err err;
913f06ca4afSHartmut Brandt struct asn_buf save = *b;
914f06ca4afSHartmut Brandt
915f06ca4afSHartmut Brandt if ((err = asn_put_temp_header(b, (ASN_TYPE_SEQUENCE |
916f06ca4afSHartmut Brandt ASN_TYPE_CONSTRUCTED), &ptr)) != ASN_ERR_OK) {
917f06ca4afSHartmut Brandt *b = save;
918f06ca4afSHartmut Brandt return (err);
919f06ca4afSHartmut Brandt }
920f06ca4afSHartmut Brandt
921f06ca4afSHartmut Brandt if ((err = asn_put_objid(b, &binding->var)) != ASN_ERR_OK) {
922f06ca4afSHartmut Brandt *b = save;
923f06ca4afSHartmut Brandt return (err);
924f06ca4afSHartmut Brandt }
925f06ca4afSHartmut Brandt
926f06ca4afSHartmut Brandt switch (binding->syntax) {
927f06ca4afSHartmut Brandt
928f06ca4afSHartmut Brandt case SNMP_SYNTAX_NULL:
929f06ca4afSHartmut Brandt err = asn_put_null(b);
930f06ca4afSHartmut Brandt break;
931f06ca4afSHartmut Brandt
932f06ca4afSHartmut Brandt case SNMP_SYNTAX_INTEGER:
933f06ca4afSHartmut Brandt err = asn_put_integer(b, binding->v.integer);
934f06ca4afSHartmut Brandt break;
935f06ca4afSHartmut Brandt
936f06ca4afSHartmut Brandt case SNMP_SYNTAX_OCTETSTRING:
937f06ca4afSHartmut Brandt err = asn_put_octetstring(b, binding->v.octetstring.octets,
938f06ca4afSHartmut Brandt binding->v.octetstring.len);
939f06ca4afSHartmut Brandt break;
940f06ca4afSHartmut Brandt
941f06ca4afSHartmut Brandt case SNMP_SYNTAX_OID:
942f06ca4afSHartmut Brandt err = asn_put_objid(b, &binding->v.oid);
943f06ca4afSHartmut Brandt break;
944f06ca4afSHartmut Brandt
945f06ca4afSHartmut Brandt case SNMP_SYNTAX_IPADDRESS:
946f06ca4afSHartmut Brandt err = asn_put_ipaddress(b, binding->v.ipaddress);
947f06ca4afSHartmut Brandt break;
948f06ca4afSHartmut Brandt
949f06ca4afSHartmut Brandt case SNMP_SYNTAX_TIMETICKS:
950f06ca4afSHartmut Brandt err = asn_put_uint32(b, ASN_APP_TIMETICKS, binding->v.uint32);
951f06ca4afSHartmut Brandt break;
952f06ca4afSHartmut Brandt
953f06ca4afSHartmut Brandt case SNMP_SYNTAX_COUNTER:
954f06ca4afSHartmut Brandt err = asn_put_uint32(b, ASN_APP_COUNTER, binding->v.uint32);
955f06ca4afSHartmut Brandt break;
956f06ca4afSHartmut Brandt
957f06ca4afSHartmut Brandt case SNMP_SYNTAX_GAUGE:
958f06ca4afSHartmut Brandt err = asn_put_uint32(b, ASN_APP_GAUGE, binding->v.uint32);
959f06ca4afSHartmut Brandt break;
960f06ca4afSHartmut Brandt
961f06ca4afSHartmut Brandt case SNMP_SYNTAX_COUNTER64:
962f06ca4afSHartmut Brandt err = asn_put_counter64(b, binding->v.counter64);
963f06ca4afSHartmut Brandt break;
964f06ca4afSHartmut Brandt
965f06ca4afSHartmut Brandt case SNMP_SYNTAX_NOSUCHOBJECT:
966f06ca4afSHartmut Brandt err = asn_put_exception(b, ASN_EXCEPT_NOSUCHOBJECT);
967f06ca4afSHartmut Brandt break;
968f06ca4afSHartmut Brandt
969f06ca4afSHartmut Brandt case SNMP_SYNTAX_NOSUCHINSTANCE:
970f06ca4afSHartmut Brandt err = asn_put_exception(b, ASN_EXCEPT_NOSUCHINSTANCE);
971f06ca4afSHartmut Brandt break;
972f06ca4afSHartmut Brandt
973f06ca4afSHartmut Brandt case SNMP_SYNTAX_ENDOFMIBVIEW:
974f06ca4afSHartmut Brandt err = asn_put_exception(b, ASN_EXCEPT_ENDOFMIBVIEW);
975f06ca4afSHartmut Brandt break;
976f06ca4afSHartmut Brandt }
977f06ca4afSHartmut Brandt
978f06ca4afSHartmut Brandt if (err != ASN_ERR_OK) {
979f06ca4afSHartmut Brandt *b = save;
980f06ca4afSHartmut Brandt return (err);
981f06ca4afSHartmut Brandt }
982f06ca4afSHartmut Brandt
983135f7de5SShteryana Shopova err = asn_commit_header(b, ptr, NULL);
984f06ca4afSHartmut Brandt if (err != ASN_ERR_OK) {
985f06ca4afSHartmut Brandt *b = save;
986f06ca4afSHartmut Brandt return (err);
987f06ca4afSHartmut Brandt }
988f06ca4afSHartmut Brandt
989f06ca4afSHartmut Brandt return (ASN_ERR_OK);
990f06ca4afSHartmut Brandt }
991f06ca4afSHartmut Brandt
992f06ca4afSHartmut Brandt /*
993f06ca4afSHartmut Brandt * Encode an PDU.
994f06ca4afSHartmut Brandt */
995f06ca4afSHartmut Brandt enum snmp_code
snmp_pdu_encode(struct snmp_pdu * pdu,struct asn_buf * resp_b)996f06ca4afSHartmut Brandt snmp_pdu_encode(struct snmp_pdu *pdu, struct asn_buf *resp_b)
997f06ca4afSHartmut Brandt {
998f06ca4afSHartmut Brandt u_int idx;
999f06ca4afSHartmut Brandt enum snmp_code err;
1000f06ca4afSHartmut Brandt
1001f06ca4afSHartmut Brandt if ((err = snmp_pdu_encode_header(resp_b, pdu)) != SNMP_CODE_OK)
1002f06ca4afSHartmut Brandt return (err);
1003f06ca4afSHartmut Brandt for (idx = 0; idx < pdu->nbindings; idx++)
100406983448SShteryana Shopova if (snmp_binding_encode(resp_b, &pdu->bindings[idx])
1005f06ca4afSHartmut Brandt != ASN_ERR_OK)
1006f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED);
1007f06ca4afSHartmut Brandt
1008f06ca4afSHartmut Brandt return (snmp_fix_encoding(resp_b, pdu));
1009f06ca4afSHartmut Brandt }
1010f06ca4afSHartmut Brandt
1011f06ca4afSHartmut Brandt static void
dump_binding(const struct snmp_value * b)1012f06ca4afSHartmut Brandt dump_binding(const struct snmp_value *b)
1013f06ca4afSHartmut Brandt {
1014f06ca4afSHartmut Brandt u_int i;
1015f06ca4afSHartmut Brandt char buf[ASN_OIDSTRLEN];
1016f06ca4afSHartmut Brandt
1017f06ca4afSHartmut Brandt snmp_printf("%s=", asn_oid2str_r(&b->var, buf));
1018f06ca4afSHartmut Brandt switch (b->syntax) {
1019f06ca4afSHartmut Brandt
1020f06ca4afSHartmut Brandt case SNMP_SYNTAX_NULL:
1021f06ca4afSHartmut Brandt snmp_printf("NULL");
1022f06ca4afSHartmut Brandt break;
1023f06ca4afSHartmut Brandt
1024f06ca4afSHartmut Brandt case SNMP_SYNTAX_INTEGER:
1025f06ca4afSHartmut Brandt snmp_printf("INTEGER %d", b->v.integer);
1026f06ca4afSHartmut Brandt break;
1027f06ca4afSHartmut Brandt
1028f06ca4afSHartmut Brandt case SNMP_SYNTAX_OCTETSTRING:
1029f06ca4afSHartmut Brandt snmp_printf("OCTET STRING %lu:", b->v.octetstring.len);
1030f06ca4afSHartmut Brandt for (i = 0; i < b->v.octetstring.len; i++)
1031f06ca4afSHartmut Brandt snmp_printf(" %02x", b->v.octetstring.octets[i]);
1032f06ca4afSHartmut Brandt break;
1033f06ca4afSHartmut Brandt
1034f06ca4afSHartmut Brandt case SNMP_SYNTAX_OID:
1035f06ca4afSHartmut Brandt snmp_printf("OID %s", asn_oid2str_r(&b->v.oid, buf));
1036f06ca4afSHartmut Brandt break;
1037f06ca4afSHartmut Brandt
1038f06ca4afSHartmut Brandt case SNMP_SYNTAX_IPADDRESS:
1039f06ca4afSHartmut Brandt snmp_printf("IPADDRESS %u.%u.%u.%u", b->v.ipaddress[0],
1040f06ca4afSHartmut Brandt b->v.ipaddress[1], b->v.ipaddress[2], b->v.ipaddress[3]);
1041f06ca4afSHartmut Brandt break;
1042f06ca4afSHartmut Brandt
1043f06ca4afSHartmut Brandt case SNMP_SYNTAX_COUNTER:
1044f06ca4afSHartmut Brandt snmp_printf("COUNTER %u", b->v.uint32);
1045f06ca4afSHartmut Brandt break;
1046f06ca4afSHartmut Brandt
1047f06ca4afSHartmut Brandt case SNMP_SYNTAX_GAUGE:
1048f06ca4afSHartmut Brandt snmp_printf("GAUGE %u", b->v.uint32);
1049f06ca4afSHartmut Brandt break;
1050f06ca4afSHartmut Brandt
1051f06ca4afSHartmut Brandt case SNMP_SYNTAX_TIMETICKS:
1052f06ca4afSHartmut Brandt snmp_printf("TIMETICKS %u", b->v.uint32);
1053f06ca4afSHartmut Brandt break;
1054f06ca4afSHartmut Brandt
1055f06ca4afSHartmut Brandt case SNMP_SYNTAX_COUNTER64:
1056f06ca4afSHartmut Brandt snmp_printf("COUNTER64 %lld", b->v.counter64);
1057f06ca4afSHartmut Brandt break;
1058f06ca4afSHartmut Brandt
1059f06ca4afSHartmut Brandt case SNMP_SYNTAX_NOSUCHOBJECT:
1060f06ca4afSHartmut Brandt snmp_printf("NoSuchObject");
1061f06ca4afSHartmut Brandt break;
1062f06ca4afSHartmut Brandt
1063f06ca4afSHartmut Brandt case SNMP_SYNTAX_NOSUCHINSTANCE:
1064f06ca4afSHartmut Brandt snmp_printf("NoSuchInstance");
1065f06ca4afSHartmut Brandt break;
1066f06ca4afSHartmut Brandt
1067f06ca4afSHartmut Brandt case SNMP_SYNTAX_ENDOFMIBVIEW:
1068f06ca4afSHartmut Brandt snmp_printf("EndOfMibView");
1069f06ca4afSHartmut Brandt break;
1070f06ca4afSHartmut Brandt
1071f06ca4afSHartmut Brandt default:
1072f06ca4afSHartmut Brandt snmp_printf("UNKNOWN SYNTAX %u", b->syntax);
1073f06ca4afSHartmut Brandt break;
1074f06ca4afSHartmut Brandt }
1075f06ca4afSHartmut Brandt }
1076f06ca4afSHartmut Brandt
1077f06ca4afSHartmut Brandt static __inline void
dump_bindings(const struct snmp_pdu * pdu)1078f06ca4afSHartmut Brandt dump_bindings(const struct snmp_pdu *pdu)
1079f06ca4afSHartmut Brandt {
1080f06ca4afSHartmut Brandt u_int i;
1081f06ca4afSHartmut Brandt
1082f06ca4afSHartmut Brandt for (i = 0; i < pdu->nbindings; i++) {
1083f06ca4afSHartmut Brandt snmp_printf(" [%u]: ", i);
1084f06ca4afSHartmut Brandt dump_binding(&pdu->bindings[i]);
1085f06ca4afSHartmut Brandt snmp_printf("\n");
1086f06ca4afSHartmut Brandt }
1087f06ca4afSHartmut Brandt }
1088f06ca4afSHartmut Brandt
1089f06ca4afSHartmut Brandt static __inline void
dump_notrap(const struct snmp_pdu * pdu)1090f06ca4afSHartmut Brandt dump_notrap(const struct snmp_pdu *pdu)
1091f06ca4afSHartmut Brandt {
1092f06ca4afSHartmut Brandt snmp_printf(" request_id=%d", pdu->request_id);
1093f06ca4afSHartmut Brandt snmp_printf(" error_status=%d", pdu->error_status);
1094f06ca4afSHartmut Brandt snmp_printf(" error_index=%d\n", pdu->error_index);
1095f06ca4afSHartmut Brandt dump_bindings(pdu);
1096f06ca4afSHartmut Brandt }
1097f06ca4afSHartmut Brandt
1098f06ca4afSHartmut Brandt void
snmp_pdu_dump(const struct snmp_pdu * pdu)1099f06ca4afSHartmut Brandt snmp_pdu_dump(const struct snmp_pdu *pdu)
1100f06ca4afSHartmut Brandt {
1101f06ca4afSHartmut Brandt char buf[ASN_OIDSTRLEN];
1102f06ca4afSHartmut Brandt const char *vers;
1103f06ca4afSHartmut Brandt static const char *types[] = {
1104f06ca4afSHartmut Brandt [SNMP_PDU_GET] = "GET",
1105f06ca4afSHartmut Brandt [SNMP_PDU_GETNEXT] = "GETNEXT",
1106f06ca4afSHartmut Brandt [SNMP_PDU_RESPONSE] = "RESPONSE",
1107f06ca4afSHartmut Brandt [SNMP_PDU_SET] = "SET",
1108f06ca4afSHartmut Brandt [SNMP_PDU_TRAP] = "TRAPv1",
1109f06ca4afSHartmut Brandt [SNMP_PDU_GETBULK] = "GETBULK",
1110f06ca4afSHartmut Brandt [SNMP_PDU_INFORM] = "INFORM",
1111f06ca4afSHartmut Brandt [SNMP_PDU_TRAP2] = "TRAPv2",
1112f06ca4afSHartmut Brandt [SNMP_PDU_REPORT] = "REPORT",
1113f06ca4afSHartmut Brandt };
1114f06ca4afSHartmut Brandt
1115f06ca4afSHartmut Brandt if (pdu->version == SNMP_V1)
1116f06ca4afSHartmut Brandt vers = "SNMPv1";
1117f06ca4afSHartmut Brandt else if (pdu->version == SNMP_V2c)
1118f06ca4afSHartmut Brandt vers = "SNMPv2c";
1119135f7de5SShteryana Shopova else if (pdu->version == SNMP_V3)
1120135f7de5SShteryana Shopova vers = "SNMPv3";
1121f06ca4afSHartmut Brandt else
1122f06ca4afSHartmut Brandt vers = "v?";
1123f06ca4afSHartmut Brandt
1124f06ca4afSHartmut Brandt switch (pdu->type) {
1125f06ca4afSHartmut Brandt case SNMP_PDU_TRAP:
1126f06ca4afSHartmut Brandt snmp_printf("%s %s '%s'", types[pdu->type], vers, pdu->community);
1127f06ca4afSHartmut Brandt snmp_printf(" enterprise=%s", asn_oid2str_r(&pdu->enterprise, buf));
1128f06ca4afSHartmut Brandt snmp_printf(" agent_addr=%u.%u.%u.%u", pdu->agent_addr[0],
1129f06ca4afSHartmut Brandt pdu->agent_addr[1], pdu->agent_addr[2], pdu->agent_addr[3]);
1130f06ca4afSHartmut Brandt snmp_printf(" generic_trap=%d", pdu->generic_trap);
1131f06ca4afSHartmut Brandt snmp_printf(" specific_trap=%d", pdu->specific_trap);
1132f06ca4afSHartmut Brandt snmp_printf(" time-stamp=%u\n", pdu->time_stamp);
1133f06ca4afSHartmut Brandt dump_bindings(pdu);
1134f06ca4afSHartmut Brandt break;
1135f06ca4afSHartmut Brandt
1136f06ca4afSHartmut Brandt case SNMP_PDU_GET:
1137f06ca4afSHartmut Brandt case SNMP_PDU_GETNEXT:
1138f06ca4afSHartmut Brandt case SNMP_PDU_RESPONSE:
1139f06ca4afSHartmut Brandt case SNMP_PDU_SET:
1140f06ca4afSHartmut Brandt case SNMP_PDU_GETBULK:
1141f06ca4afSHartmut Brandt case SNMP_PDU_INFORM:
1142f06ca4afSHartmut Brandt case SNMP_PDU_TRAP2:
1143f06ca4afSHartmut Brandt case SNMP_PDU_REPORT:
1144f06ca4afSHartmut Brandt snmp_printf("%s %s '%s'", types[pdu->type], vers, pdu->community);
1145f06ca4afSHartmut Brandt dump_notrap(pdu);
1146f06ca4afSHartmut Brandt break;
1147f06ca4afSHartmut Brandt
1148f06ca4afSHartmut Brandt default:
1149f06ca4afSHartmut Brandt snmp_printf("bad pdu type %u\n", pdu->type);
1150f06ca4afSHartmut Brandt break;
1151f06ca4afSHartmut Brandt }
1152f06ca4afSHartmut Brandt }
1153f06ca4afSHartmut Brandt
1154f06ca4afSHartmut Brandt void
snmp_value_free(struct snmp_value * value)1155f06ca4afSHartmut Brandt snmp_value_free(struct snmp_value *value)
1156f06ca4afSHartmut Brandt {
1157*6c9b7542SEnji Cooper
1158*6c9b7542SEnji Cooper if (value->syntax == SNMP_SYNTAX_OCTETSTRING) {
1159f06ca4afSHartmut Brandt free(value->v.octetstring.octets);
1160*6c9b7542SEnji Cooper value->v.octetstring.octets = NULL;
1161*6c9b7542SEnji Cooper }
1162f06ca4afSHartmut Brandt value->syntax = SNMP_SYNTAX_NULL;
1163f06ca4afSHartmut Brandt }
1164f06ca4afSHartmut Brandt
1165f06ca4afSHartmut Brandt int
snmp_value_copy(struct snmp_value * to,const struct snmp_value * from)1166f06ca4afSHartmut Brandt snmp_value_copy(struct snmp_value *to, const struct snmp_value *from)
1167f06ca4afSHartmut Brandt {
1168f06ca4afSHartmut Brandt to->var = from->var;
1169f06ca4afSHartmut Brandt to->syntax = from->syntax;
1170f06ca4afSHartmut Brandt
1171f06ca4afSHartmut Brandt if (from->syntax == SNMP_SYNTAX_OCTETSTRING) {
1172f06ca4afSHartmut Brandt if ((to->v.octetstring.len = from->v.octetstring.len) == 0)
1173f06ca4afSHartmut Brandt to->v.octetstring.octets = NULL;
1174f06ca4afSHartmut Brandt else {
1175f06ca4afSHartmut Brandt to->v.octetstring.octets = malloc(to->v.octetstring.len);
1176f06ca4afSHartmut Brandt if (to->v.octetstring.octets == NULL)
1177f06ca4afSHartmut Brandt return (-1);
1178f06ca4afSHartmut Brandt (void)memcpy(to->v.octetstring.octets,
1179f06ca4afSHartmut Brandt from->v.octetstring.octets, to->v.octetstring.len);
1180f06ca4afSHartmut Brandt }
1181f06ca4afSHartmut Brandt } else
1182f06ca4afSHartmut Brandt to->v = from->v;
1183f06ca4afSHartmut Brandt return (0);
1184f06ca4afSHartmut Brandt }
1185f06ca4afSHartmut Brandt
1186f06ca4afSHartmut Brandt void
snmp_pdu_init_secparams(struct snmp_pdu * pdu)118772cd7a52SShteryana Shopova snmp_pdu_init_secparams(struct snmp_pdu *pdu)
1188135f7de5SShteryana Shopova {
1189135f7de5SShteryana Shopova int32_t rval;
1190135f7de5SShteryana Shopova
119172cd7a52SShteryana Shopova if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH)
1192135f7de5SShteryana Shopova pdu->flags |= SNMP_MSG_AUTH_FLAG;
1193135f7de5SShteryana Shopova
119472cd7a52SShteryana Shopova switch (pdu->user.priv_proto) {
1195135f7de5SShteryana Shopova case SNMP_PRIV_DES:
119672cd7a52SShteryana Shopova memcpy(pdu->msg_salt, &pdu->engine.engine_boots,
119772cd7a52SShteryana Shopova sizeof(pdu->engine.engine_boots));
1198135f7de5SShteryana Shopova rval = random();
119972cd7a52SShteryana Shopova memcpy(pdu->msg_salt + sizeof(pdu->engine.engine_boots), &rval,
1200135f7de5SShteryana Shopova sizeof(int32_t));
1201135f7de5SShteryana Shopova pdu->flags |= SNMP_MSG_PRIV_FLAG;
1202135f7de5SShteryana Shopova break;
1203135f7de5SShteryana Shopova case SNMP_PRIV_AES:
1204135f7de5SShteryana Shopova rval = random();
1205135f7de5SShteryana Shopova memcpy(pdu->msg_salt, &rval, sizeof(int32_t));
1206135f7de5SShteryana Shopova rval = random();
1207135f7de5SShteryana Shopova memcpy(pdu->msg_salt + sizeof(int32_t), &rval, sizeof(int32_t));
1208135f7de5SShteryana Shopova pdu->flags |= SNMP_MSG_PRIV_FLAG;
1209135f7de5SShteryana Shopova break;
1210135f7de5SShteryana Shopova default:
1211135f7de5SShteryana Shopova break;
1212135f7de5SShteryana Shopova }
1213135f7de5SShteryana Shopova }
1214135f7de5SShteryana Shopova
1215135f7de5SShteryana Shopova void
snmp_pdu_free(struct snmp_pdu * pdu)1216f06ca4afSHartmut Brandt snmp_pdu_free(struct snmp_pdu *pdu)
1217f06ca4afSHartmut Brandt {
1218f06ca4afSHartmut Brandt u_int i;
1219f06ca4afSHartmut Brandt
1220f06ca4afSHartmut Brandt for (i = 0; i < pdu->nbindings; i++)
1221f06ca4afSHartmut Brandt snmp_value_free(&pdu->bindings[i]);
1222*6c9b7542SEnji Cooper pdu->nbindings = 0;
1223f06ca4afSHartmut Brandt }
1224f06ca4afSHartmut Brandt
1225f06ca4afSHartmut Brandt /*
1226f06ca4afSHartmut Brandt * Parse an ASCII SNMP value into the binary form
1227f06ca4afSHartmut Brandt */
1228f06ca4afSHartmut Brandt int
snmp_value_parse(const char * str,enum snmp_syntax syntax,union snmp_values * v)1229f06ca4afSHartmut Brandt snmp_value_parse(const char *str, enum snmp_syntax syntax, union snmp_values *v)
1230f06ca4afSHartmut Brandt {
1231f06ca4afSHartmut Brandt char *end;
1232f06ca4afSHartmut Brandt
1233f06ca4afSHartmut Brandt switch (syntax) {
1234f06ca4afSHartmut Brandt
1235f06ca4afSHartmut Brandt case SNMP_SYNTAX_NULL:
1236f06ca4afSHartmut Brandt case SNMP_SYNTAX_NOSUCHOBJECT:
1237f06ca4afSHartmut Brandt case SNMP_SYNTAX_NOSUCHINSTANCE:
1238f06ca4afSHartmut Brandt case SNMP_SYNTAX_ENDOFMIBVIEW:
1239f06ca4afSHartmut Brandt if (*str != '\0')
1240f06ca4afSHartmut Brandt return (-1);
1241f06ca4afSHartmut Brandt return (0);
1242f06ca4afSHartmut Brandt
1243f06ca4afSHartmut Brandt case SNMP_SYNTAX_INTEGER:
1244f06ca4afSHartmut Brandt v->integer = strtoll(str, &end, 0);
1245f06ca4afSHartmut Brandt if (*end != '\0')
1246f06ca4afSHartmut Brandt return (-1);
1247f06ca4afSHartmut Brandt return (0);
1248f06ca4afSHartmut Brandt
1249f06ca4afSHartmut Brandt case SNMP_SYNTAX_OCTETSTRING:
1250f06ca4afSHartmut Brandt {
1251f06ca4afSHartmut Brandt u_long len; /* actual length of string */
1252f06ca4afSHartmut Brandt u_long alloc; /* allocate length of string */
1253f06ca4afSHartmut Brandt u_char *octs; /* actual octets */
1254f06ca4afSHartmut Brandt u_long oct; /* actual octet */
1255f06ca4afSHartmut Brandt u_char *nocts; /* to avoid memory leak */
1256f06ca4afSHartmut Brandt u_char c; /* actual character */
1257f06ca4afSHartmut Brandt
1258f06ca4afSHartmut Brandt # define STUFFC(C) \
1259f06ca4afSHartmut Brandt if (alloc == len) { \
1260f06ca4afSHartmut Brandt alloc += 100; \
1261f06ca4afSHartmut Brandt if ((nocts = realloc(octs, alloc)) == NULL) { \
1262f06ca4afSHartmut Brandt free(octs); \
1263f06ca4afSHartmut Brandt return (-1); \
1264f06ca4afSHartmut Brandt } \
1265f06ca4afSHartmut Brandt octs = nocts; \
1266f06ca4afSHartmut Brandt } \
1267f06ca4afSHartmut Brandt octs[len++] = (C);
1268f06ca4afSHartmut Brandt
1269f06ca4afSHartmut Brandt len = alloc = 0;
1270f06ca4afSHartmut Brandt octs = NULL;
1271f06ca4afSHartmut Brandt
1272f06ca4afSHartmut Brandt if (*str == '"') {
1273f06ca4afSHartmut Brandt str++;
1274f06ca4afSHartmut Brandt while((c = *str++) != '\0') {
1275f06ca4afSHartmut Brandt if (c == '"') {
1276f06ca4afSHartmut Brandt if (*str != '\0') {
1277f06ca4afSHartmut Brandt free(octs);
1278f06ca4afSHartmut Brandt return (-1);
1279f06ca4afSHartmut Brandt }
1280f06ca4afSHartmut Brandt break;
1281f06ca4afSHartmut Brandt }
1282f06ca4afSHartmut Brandt if (c == '\\') {
1283f06ca4afSHartmut Brandt switch (c = *str++) {
1284f06ca4afSHartmut Brandt
1285f06ca4afSHartmut Brandt case '\\':
1286f06ca4afSHartmut Brandt break;
1287f06ca4afSHartmut Brandt case 'a':
1288f06ca4afSHartmut Brandt c = '\a';
1289f06ca4afSHartmut Brandt break;
1290f06ca4afSHartmut Brandt case 'b':
1291f06ca4afSHartmut Brandt c = '\b';
1292f06ca4afSHartmut Brandt break;
1293f06ca4afSHartmut Brandt case 'f':
1294f06ca4afSHartmut Brandt c = '\f';
1295f06ca4afSHartmut Brandt break;
1296f06ca4afSHartmut Brandt case 'n':
1297f06ca4afSHartmut Brandt c = '\n';
1298f06ca4afSHartmut Brandt break;
1299f06ca4afSHartmut Brandt case 'r':
1300f06ca4afSHartmut Brandt c = '\r';
1301f06ca4afSHartmut Brandt break;
1302f06ca4afSHartmut Brandt case 't':
1303f06ca4afSHartmut Brandt c = '\t';
1304f06ca4afSHartmut Brandt break;
1305f06ca4afSHartmut Brandt case 'v':
1306f06ca4afSHartmut Brandt c = '\v';
1307f06ca4afSHartmut Brandt break;
1308f06ca4afSHartmut Brandt case 'x':
1309f06ca4afSHartmut Brandt c = 0;
1310f06ca4afSHartmut Brandt if (!isxdigit(*str))
1311f06ca4afSHartmut Brandt break;
1312f06ca4afSHartmut Brandt if (isdigit(*str))
1313f06ca4afSHartmut Brandt c = *str++ - '0';
1314f06ca4afSHartmut Brandt else if (isupper(*str))
1315f06ca4afSHartmut Brandt c = *str++ - 'A' + 10;
1316f06ca4afSHartmut Brandt else
1317f06ca4afSHartmut Brandt c = *str++ - 'a' + 10;
1318f06ca4afSHartmut Brandt if (!isxdigit(*str))
1319f06ca4afSHartmut Brandt break;
1320f06ca4afSHartmut Brandt if (isdigit(*str))
1321f06ca4afSHartmut Brandt c += *str++ - '0';
1322f06ca4afSHartmut Brandt else if (isupper(*str))
1323f06ca4afSHartmut Brandt c += *str++ - 'A' + 10;
1324f06ca4afSHartmut Brandt else
1325f06ca4afSHartmut Brandt c += *str++ - 'a' + 10;
1326f06ca4afSHartmut Brandt break;
1327f06ca4afSHartmut Brandt case '0': case '1': case '2':
1328f06ca4afSHartmut Brandt case '3': case '4': case '5':
1329f06ca4afSHartmut Brandt case '6': case '7':
1330f06ca4afSHartmut Brandt c = *str++ - '0';
1331f06ca4afSHartmut Brandt if (*str < '0' || *str > '7')
1332f06ca4afSHartmut Brandt break;
1333f06ca4afSHartmut Brandt c = *str++ - '0';
1334f06ca4afSHartmut Brandt if (*str < '0' || *str > '7')
1335f06ca4afSHartmut Brandt break;
1336f06ca4afSHartmut Brandt c = *str++ - '0';
1337f06ca4afSHartmut Brandt break;
1338f06ca4afSHartmut Brandt default:
1339f06ca4afSHartmut Brandt break;
1340f06ca4afSHartmut Brandt }
1341f06ca4afSHartmut Brandt }
1342f06ca4afSHartmut Brandt STUFFC(c);
1343f06ca4afSHartmut Brandt }
1344f06ca4afSHartmut Brandt } else {
1345f06ca4afSHartmut Brandt while (*str != '\0') {
1346f06ca4afSHartmut Brandt oct = strtoul(str, &end, 16);
1347f06ca4afSHartmut Brandt str = end;
1348f06ca4afSHartmut Brandt if (oct > 0xff) {
1349f06ca4afSHartmut Brandt free(octs);
1350f06ca4afSHartmut Brandt return (-1);
1351f06ca4afSHartmut Brandt }
1352f06ca4afSHartmut Brandt STUFFC(oct);
1353f06ca4afSHartmut Brandt if (*str == ':')
1354f06ca4afSHartmut Brandt str++;
1355f06ca4afSHartmut Brandt else if(*str != '\0') {
1356f06ca4afSHartmut Brandt free(octs);
1357f06ca4afSHartmut Brandt return (-1);
1358f06ca4afSHartmut Brandt }
1359f06ca4afSHartmut Brandt }
1360f06ca4afSHartmut Brandt }
1361f06ca4afSHartmut Brandt v->octetstring.octets = octs;
1362f06ca4afSHartmut Brandt v->octetstring.len = len;
1363f06ca4afSHartmut Brandt return (0);
1364f06ca4afSHartmut Brandt # undef STUFFC
1365f06ca4afSHartmut Brandt }
1366f06ca4afSHartmut Brandt
1367f06ca4afSHartmut Brandt case SNMP_SYNTAX_OID:
1368f06ca4afSHartmut Brandt {
1369f06ca4afSHartmut Brandt u_long subid;
1370f06ca4afSHartmut Brandt
1371f06ca4afSHartmut Brandt v->oid.len = 0;
1372f06ca4afSHartmut Brandt
1373f06ca4afSHartmut Brandt for (;;) {
1374f06ca4afSHartmut Brandt if (v->oid.len == ASN_MAXOIDLEN)
1375f06ca4afSHartmut Brandt return (-1);
1376f06ca4afSHartmut Brandt subid = strtoul(str, &end, 10);
1377f06ca4afSHartmut Brandt str = end;
1378f06ca4afSHartmut Brandt if (subid > ASN_MAXID)
1379f06ca4afSHartmut Brandt return (-1);
1380f06ca4afSHartmut Brandt v->oid.subs[v->oid.len++] = (asn_subid_t)subid;
1381f06ca4afSHartmut Brandt if (*str == '\0')
1382f06ca4afSHartmut Brandt break;
1383f06ca4afSHartmut Brandt if (*str != '.')
1384f06ca4afSHartmut Brandt return (-1);
1385f06ca4afSHartmut Brandt str++;
1386f06ca4afSHartmut Brandt }
1387f06ca4afSHartmut Brandt return (0);
1388f06ca4afSHartmut Brandt }
1389f06ca4afSHartmut Brandt
1390f06ca4afSHartmut Brandt case SNMP_SYNTAX_IPADDRESS:
1391f06ca4afSHartmut Brandt {
1392f06ca4afSHartmut Brandt struct hostent *he;
1393f06ca4afSHartmut Brandt
13946521e5f8SEnji Cooper if (inet_pton(AF_INET, str, &v->ipaddress) == 1)
1395f06ca4afSHartmut Brandt return (0);
13966521e5f8SEnji Cooper if ((he = gethostbyname2(str, AF_INET)) == NULL)
1397f06ca4afSHartmut Brandt return (-1);
1398f06ca4afSHartmut Brandt if (he->h_addrtype != AF_INET)
1399f06ca4afSHartmut Brandt return (-1);
1400f06ca4afSHartmut Brandt
14016521e5f8SEnji Cooper memcpy(v->ipaddress, he->h_addr, sizeof(v->ipaddress));
14026521e5f8SEnji Cooper
1403f06ca4afSHartmut Brandt return (0);
1404f06ca4afSHartmut Brandt }
1405f06ca4afSHartmut Brandt
1406f06ca4afSHartmut Brandt case SNMP_SYNTAX_COUNTER:
1407f06ca4afSHartmut Brandt case SNMP_SYNTAX_GAUGE:
1408f06ca4afSHartmut Brandt case SNMP_SYNTAX_TIMETICKS:
1409f06ca4afSHartmut Brandt {
1410896052c1SHartmut Brandt uint64_t sub;
1411f06ca4afSHartmut Brandt
1412f06ca4afSHartmut Brandt sub = strtoull(str, &end, 0);
1413f06ca4afSHartmut Brandt if (*end != '\0' || sub > 0xffffffff)
1414f06ca4afSHartmut Brandt return (-1);
1415896052c1SHartmut Brandt v->uint32 = (uint32_t)sub;
1416f06ca4afSHartmut Brandt return (0);
1417f06ca4afSHartmut Brandt }
1418f06ca4afSHartmut Brandt
1419f06ca4afSHartmut Brandt case SNMP_SYNTAX_COUNTER64:
1420f06ca4afSHartmut Brandt v->counter64 = strtoull(str, &end, 0);
1421f06ca4afSHartmut Brandt if (*end != '\0')
1422f06ca4afSHartmut Brandt return (-1);
1423f06ca4afSHartmut Brandt return (0);
1424f06ca4afSHartmut Brandt }
1425f06ca4afSHartmut Brandt abort();
1426f06ca4afSHartmut Brandt }
1427f06ca4afSHartmut Brandt
1428f06ca4afSHartmut Brandt static void
snmp_error_func(const char * fmt,...)1429f06ca4afSHartmut Brandt snmp_error_func(const char *fmt, ...)
1430f06ca4afSHartmut Brandt {
1431f06ca4afSHartmut Brandt va_list ap;
1432f06ca4afSHartmut Brandt
1433f06ca4afSHartmut Brandt va_start(ap, fmt);
1434f06ca4afSHartmut Brandt fprintf(stderr, "SNMP: ");
1435f06ca4afSHartmut Brandt vfprintf(stderr, fmt, ap);
1436f06ca4afSHartmut Brandt fprintf(stderr, "\n");
1437f06ca4afSHartmut Brandt va_end(ap);
1438f06ca4afSHartmut Brandt }
1439f06ca4afSHartmut Brandt
1440f06ca4afSHartmut Brandt static void
snmp_printf_func(const char * fmt,...)1441f06ca4afSHartmut Brandt snmp_printf_func(const char *fmt, ...)
1442f06ca4afSHartmut Brandt {
1443f06ca4afSHartmut Brandt va_list ap;
1444f06ca4afSHartmut Brandt
1445f06ca4afSHartmut Brandt va_start(ap, fmt);
1446f06ca4afSHartmut Brandt vfprintf(stderr, fmt, ap);
1447f06ca4afSHartmut Brandt va_end(ap);
1448f06ca4afSHartmut Brandt }
1449