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> 41f06ca4afSHartmut Brandt #include <stdio.h> 42f06ca4afSHartmut Brandt #include <stdlib.h> 43f06ca4afSHartmut Brandt #include <stddef.h> 44f06ca4afSHartmut Brandt #include <stdarg.h> 45165c5d31SHartmut Brandt #ifdef HAVE_STDINT_H 46896052c1SHartmut Brandt #include <stdint.h> 47165c5d31SHartmut Brandt #elif defined(HAVE_INTTYPES_H) 48165c5d31SHartmut Brandt #include <inttypes.h> 49165c5d31SHartmut Brandt #endif 50f06ca4afSHartmut Brandt #include <string.h> 51f06ca4afSHartmut Brandt #include <ctype.h> 52f06ca4afSHartmut Brandt #include <netdb.h> 53f06ca4afSHartmut Brandt #include <errno.h> 54f06ca4afSHartmut Brandt 55f06ca4afSHartmut Brandt #include "asn1.h" 56f06ca4afSHartmut Brandt #include "snmp.h" 57f06ca4afSHartmut Brandt #include "snmppriv.h" 58f06ca4afSHartmut Brandt 59f06ca4afSHartmut Brandt static void snmp_error_func(const char *, ...); 60f06ca4afSHartmut Brandt static void snmp_printf_func(const char *, ...); 61f06ca4afSHartmut Brandt 62f06ca4afSHartmut Brandt void (*snmp_error)(const char *, ...) = snmp_error_func; 63f06ca4afSHartmut Brandt void (*snmp_printf)(const char *, ...) = snmp_printf_func; 64f06ca4afSHartmut Brandt 65f06ca4afSHartmut Brandt /* 66f06ca4afSHartmut Brandt * Get the next variable binding from the list. 67f06ca4afSHartmut Brandt * ASN errors on the sequence or the OID are always fatal. 68f06ca4afSHartmut Brandt */ 69f06ca4afSHartmut Brandt static enum asn_err 70f06ca4afSHartmut Brandt get_var_binding(struct asn_buf *b, struct snmp_value *binding) 71f06ca4afSHartmut Brandt { 72f06ca4afSHartmut Brandt u_char type; 73f06ca4afSHartmut Brandt asn_len_t len, trailer; 74f06ca4afSHartmut Brandt enum asn_err err; 75f06ca4afSHartmut Brandt 76f06ca4afSHartmut Brandt if (asn_get_sequence(b, &len) != ASN_ERR_OK) { 77f06ca4afSHartmut Brandt snmp_error("cannot parse varbind header"); 78f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 79f06ca4afSHartmut Brandt } 80f06ca4afSHartmut Brandt 81f06ca4afSHartmut Brandt /* temporary truncate the length so that the parser does not 82f06ca4afSHartmut Brandt * eat up bytes behind the sequence in the case the encoding is 83f06ca4afSHartmut Brandt * wrong of inner elements. */ 84f06ca4afSHartmut Brandt trailer = b->asn_len - len; 85f06ca4afSHartmut Brandt b->asn_len = len; 86f06ca4afSHartmut Brandt 87f06ca4afSHartmut Brandt if (asn_get_objid(b, &binding->var) != ASN_ERR_OK) { 88f06ca4afSHartmut Brandt snmp_error("cannot parse binding objid"); 89f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 90f06ca4afSHartmut Brandt } 91f06ca4afSHartmut Brandt if (asn_get_header(b, &type, &len) != ASN_ERR_OK) { 92f06ca4afSHartmut Brandt snmp_error("cannot parse binding value header"); 93f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 94f06ca4afSHartmut Brandt } 95f06ca4afSHartmut Brandt 96f06ca4afSHartmut Brandt switch (type) { 97f06ca4afSHartmut Brandt 98f06ca4afSHartmut Brandt case ASN_TYPE_NULL: 99f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_NULL; 100f06ca4afSHartmut Brandt err = asn_get_null_raw(b, len); 101f06ca4afSHartmut Brandt break; 102f06ca4afSHartmut Brandt 103f06ca4afSHartmut Brandt case ASN_TYPE_INTEGER: 104f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_INTEGER; 105f06ca4afSHartmut Brandt err = asn_get_integer_raw(b, len, &binding->v.integer); 106f06ca4afSHartmut Brandt break; 107f06ca4afSHartmut Brandt 108f06ca4afSHartmut Brandt case ASN_TYPE_OCTETSTRING: 109f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_OCTETSTRING; 110f06ca4afSHartmut Brandt binding->v.octetstring.octets = malloc(len); 111f06ca4afSHartmut Brandt if (binding->v.octetstring.octets == NULL) { 112f06ca4afSHartmut Brandt snmp_error("%s", strerror(errno)); 113f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 114f06ca4afSHartmut Brandt } 115f06ca4afSHartmut Brandt binding->v.octetstring.len = len; 116f06ca4afSHartmut Brandt err = asn_get_octetstring_raw(b, len, 117f06ca4afSHartmut Brandt binding->v.octetstring.octets, 118f06ca4afSHartmut Brandt &binding->v.octetstring.len); 119f06ca4afSHartmut Brandt if (ASN_ERR_STOPPED(err)) { 120f06ca4afSHartmut Brandt free(binding->v.octetstring.octets); 121f06ca4afSHartmut Brandt binding->v.octetstring.octets = NULL; 122f06ca4afSHartmut Brandt } 123f06ca4afSHartmut Brandt break; 124f06ca4afSHartmut Brandt 125f06ca4afSHartmut Brandt case ASN_TYPE_OBJID: 126f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_OID; 127f06ca4afSHartmut Brandt err = asn_get_objid_raw(b, len, &binding->v.oid); 128f06ca4afSHartmut Brandt break; 129f06ca4afSHartmut Brandt 130f06ca4afSHartmut Brandt case ASN_CLASS_APPLICATION|ASN_APP_IPADDRESS: 131f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_IPADDRESS; 132f06ca4afSHartmut Brandt err = asn_get_ipaddress_raw(b, len, binding->v.ipaddress); 133f06ca4afSHartmut Brandt break; 134f06ca4afSHartmut Brandt 135f06ca4afSHartmut Brandt case ASN_CLASS_APPLICATION|ASN_APP_TIMETICKS: 136f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_TIMETICKS; 137f06ca4afSHartmut Brandt err = asn_get_uint32_raw(b, len, &binding->v.uint32); 138f06ca4afSHartmut Brandt break; 139f06ca4afSHartmut Brandt 140f06ca4afSHartmut Brandt case ASN_CLASS_APPLICATION|ASN_APP_COUNTER: 141f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_COUNTER; 142f06ca4afSHartmut Brandt err = asn_get_uint32_raw(b, len, &binding->v.uint32); 143f06ca4afSHartmut Brandt break; 144f06ca4afSHartmut Brandt 145f06ca4afSHartmut Brandt case ASN_CLASS_APPLICATION|ASN_APP_GAUGE: 146f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_GAUGE; 147f06ca4afSHartmut Brandt err = asn_get_uint32_raw(b, len, &binding->v.uint32); 148f06ca4afSHartmut Brandt break; 149f06ca4afSHartmut Brandt 150f06ca4afSHartmut Brandt case ASN_CLASS_APPLICATION|ASN_APP_COUNTER64: 151f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_COUNTER64; 152f06ca4afSHartmut Brandt err = asn_get_counter64_raw(b, len, &binding->v.counter64); 153f06ca4afSHartmut Brandt break; 154f06ca4afSHartmut Brandt 155f06ca4afSHartmut Brandt case ASN_CLASS_CONTEXT | ASN_EXCEPT_NOSUCHOBJECT: 156f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_NOSUCHOBJECT; 157f06ca4afSHartmut Brandt err = asn_get_null_raw(b, len); 158f06ca4afSHartmut Brandt break; 159f06ca4afSHartmut Brandt 160f06ca4afSHartmut Brandt case ASN_CLASS_CONTEXT | ASN_EXCEPT_NOSUCHINSTANCE: 161f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_NOSUCHINSTANCE; 162f06ca4afSHartmut Brandt err = asn_get_null_raw(b, len); 163f06ca4afSHartmut Brandt break; 164f06ca4afSHartmut Brandt 165f06ca4afSHartmut Brandt case ASN_CLASS_CONTEXT | ASN_EXCEPT_ENDOFMIBVIEW: 166f06ca4afSHartmut Brandt binding->syntax = SNMP_SYNTAX_ENDOFMIBVIEW; 167f06ca4afSHartmut Brandt err = asn_get_null_raw(b, len); 168f06ca4afSHartmut Brandt break; 169f06ca4afSHartmut Brandt 170f06ca4afSHartmut Brandt default: 171f06ca4afSHartmut Brandt if ((err = asn_skip(b, len)) == ASN_ERR_OK) 172f06ca4afSHartmut Brandt err = ASN_ERR_TAG; 173f06ca4afSHartmut Brandt snmp_error("bad binding value type 0x%x", type); 174f06ca4afSHartmut Brandt break; 175f06ca4afSHartmut Brandt } 176f06ca4afSHartmut Brandt 177f06ca4afSHartmut Brandt if (ASN_ERR_STOPPED(err)) { 178f06ca4afSHartmut Brandt snmp_error("cannot parse binding value"); 179f06ca4afSHartmut Brandt return (err); 180f06ca4afSHartmut Brandt } 181f06ca4afSHartmut Brandt 182f06ca4afSHartmut Brandt if (b->asn_len != 0) 183f06ca4afSHartmut Brandt snmp_error("ignoring junk at end of binding"); 184f06ca4afSHartmut Brandt 185f06ca4afSHartmut Brandt b->asn_len = trailer; 186f06ca4afSHartmut Brandt 187f06ca4afSHartmut Brandt return (err); 188f06ca4afSHartmut Brandt } 189f06ca4afSHartmut Brandt 190f06ca4afSHartmut Brandt /* 191f06ca4afSHartmut Brandt * Parse the different PDUs contents. Any ASN error in the outer components 192f06ca4afSHartmut Brandt * are fatal. Only errors in variable values may be tolerated. If all 193f06ca4afSHartmut Brandt * components can be parsed it returns either ASN_ERR_OK or the first 194f06ca4afSHartmut Brandt * error that was found. 195f06ca4afSHartmut Brandt */ 196f06ca4afSHartmut Brandt enum asn_err 197f06ca4afSHartmut Brandt snmp_parse_pdus_hdr(struct asn_buf *b, struct snmp_pdu *pdu, asn_len_t *lenp) 198f06ca4afSHartmut Brandt { 199f06ca4afSHartmut Brandt if (pdu->type == SNMP_PDU_TRAP) { 200f06ca4afSHartmut Brandt if (asn_get_objid(b, &pdu->enterprise) != ASN_ERR_OK) { 201f06ca4afSHartmut Brandt snmp_error("cannot parse trap enterprise"); 202f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 203f06ca4afSHartmut Brandt } 204f06ca4afSHartmut Brandt if (asn_get_ipaddress(b, pdu->agent_addr) != ASN_ERR_OK) { 205f06ca4afSHartmut Brandt snmp_error("cannot parse trap agent address"); 206f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 207f06ca4afSHartmut Brandt } 208f06ca4afSHartmut Brandt if (asn_get_integer(b, &pdu->generic_trap) != ASN_ERR_OK) { 209f06ca4afSHartmut Brandt snmp_error("cannot parse 'generic-trap'"); 210f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 211f06ca4afSHartmut Brandt } 212f06ca4afSHartmut Brandt if (asn_get_integer(b, &pdu->specific_trap) != ASN_ERR_OK) { 213f06ca4afSHartmut Brandt snmp_error("cannot parse 'specific-trap'"); 214f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 215f06ca4afSHartmut Brandt } 216f06ca4afSHartmut Brandt if (asn_get_timeticks(b, &pdu->time_stamp) != ASN_ERR_OK) { 217f06ca4afSHartmut Brandt snmp_error("cannot parse trap 'time-stamp'"); 218f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 219f06ca4afSHartmut Brandt } 220f06ca4afSHartmut Brandt } else { 221f06ca4afSHartmut Brandt if (asn_get_integer(b, &pdu->request_id) != ASN_ERR_OK) { 222f06ca4afSHartmut Brandt snmp_error("cannot parse 'request-id'"); 223f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 224f06ca4afSHartmut Brandt } 225f06ca4afSHartmut Brandt if (asn_get_integer(b, &pdu->error_status) != ASN_ERR_OK) { 226f06ca4afSHartmut Brandt snmp_error("cannot parse 'error_status'"); 227f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 228f06ca4afSHartmut Brandt } 229f06ca4afSHartmut Brandt if (asn_get_integer(b, &pdu->error_index) != ASN_ERR_OK) { 230f06ca4afSHartmut Brandt snmp_error("cannot parse 'error_index'"); 231f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 232f06ca4afSHartmut Brandt } 233f06ca4afSHartmut Brandt } 234f06ca4afSHartmut Brandt 235f06ca4afSHartmut Brandt if (asn_get_sequence(b, lenp) != ASN_ERR_OK) { 236f06ca4afSHartmut Brandt snmp_error("cannot get varlist header"); 237f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 238f06ca4afSHartmut Brandt } 239f06ca4afSHartmut Brandt 240f06ca4afSHartmut Brandt return (ASN_ERR_OK); 241f06ca4afSHartmut Brandt } 242f06ca4afSHartmut Brandt 243f06ca4afSHartmut Brandt static enum asn_err 244f06ca4afSHartmut Brandt parse_pdus(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip) 245f06ca4afSHartmut Brandt { 246f06ca4afSHartmut Brandt asn_len_t len, trailer; 247f06ca4afSHartmut Brandt struct snmp_value *v; 248f06ca4afSHartmut Brandt enum asn_err err, err1; 249f06ca4afSHartmut Brandt 250f06ca4afSHartmut Brandt err = snmp_parse_pdus_hdr(b, pdu, &len); 251f06ca4afSHartmut Brandt if (ASN_ERR_STOPPED(err)) 252f06ca4afSHartmut Brandt return (err); 253f06ca4afSHartmut Brandt 254f06ca4afSHartmut Brandt trailer = b->asn_len - len; 255f06ca4afSHartmut Brandt 256f06ca4afSHartmut Brandt v = pdu->bindings; 257f06ca4afSHartmut Brandt err = ASN_ERR_OK; 258f06ca4afSHartmut Brandt while (b->asn_len != 0) { 259f06ca4afSHartmut Brandt if (pdu->nbindings == SNMP_MAX_BINDINGS) { 260f06ca4afSHartmut Brandt snmp_error("too many bindings (> %u) in PDU", 261f06ca4afSHartmut Brandt SNMP_MAX_BINDINGS); 262f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 263f06ca4afSHartmut Brandt } 264f06ca4afSHartmut Brandt err1 = get_var_binding(b, v); 265f06ca4afSHartmut Brandt if (ASN_ERR_STOPPED(err1)) 266f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 267f06ca4afSHartmut Brandt if (err1 != ASN_ERR_OK && err == ASN_ERR_OK) { 268f06ca4afSHartmut Brandt err = err1; 269f06ca4afSHartmut Brandt *ip = pdu->nbindings + 1; 270f06ca4afSHartmut Brandt } 271f06ca4afSHartmut Brandt pdu->nbindings++; 272f06ca4afSHartmut Brandt v++; 273f06ca4afSHartmut Brandt } 274f06ca4afSHartmut Brandt 275f06ca4afSHartmut Brandt b->asn_len = trailer; 276f06ca4afSHartmut Brandt 277f06ca4afSHartmut Brandt return (err); 278f06ca4afSHartmut Brandt } 279f06ca4afSHartmut Brandt 280135f7de5SShteryana Shopova 281135f7de5SShteryana Shopova static enum asn_err 282135f7de5SShteryana Shopova parse_secparams(struct asn_buf *b, struct snmp_pdu *pdu) 283f06ca4afSHartmut Brandt { 284135f7de5SShteryana Shopova asn_len_t octs_len; 285135f7de5SShteryana Shopova u_char buf[256]; /* XXX: calc max possible size here */ 286135f7de5SShteryana Shopova struct asn_buf tb; 287f06ca4afSHartmut Brandt 288135f7de5SShteryana Shopova memset(buf, 0, 256); 289135f7de5SShteryana Shopova tb.asn_ptr = buf; 290135f7de5SShteryana Shopova tb.asn_len = 256; 291135f7de5SShteryana Shopova 292135f7de5SShteryana Shopova if (asn_get_octetstring(b, buf, &tb.asn_len) != ASN_ERR_OK) { 293135f7de5SShteryana Shopova snmp_error("cannot parse usm header"); 294f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 295f06ca4afSHartmut Brandt } 296f06ca4afSHartmut Brandt 297135f7de5SShteryana Shopova if (asn_get_sequence(&tb, &octs_len) != ASN_ERR_OK) { 298135f7de5SShteryana Shopova snmp_error("cannot decode usm header"); 299f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 300f06ca4afSHartmut Brandt } 301f06ca4afSHartmut Brandt 302135f7de5SShteryana Shopova octs_len = SNMP_ENGINE_ID_SIZ; 303135f7de5SShteryana Shopova if (asn_get_octetstring(&tb, (u_char *)&pdu->engine.engine_id, 304135f7de5SShteryana Shopova &octs_len) != ASN_ERR_OK) { 305135f7de5SShteryana Shopova snmp_error("cannot decode msg engine id"); 306f06ca4afSHartmut Brandt return (ASN_ERR_FAILED); 307f06ca4afSHartmut Brandt } 308135f7de5SShteryana Shopova pdu->engine.engine_len = octs_len; 309135f7de5SShteryana Shopova 310135f7de5SShteryana Shopova if (asn_get_integer(&tb, &pdu->engine.engine_boots) != ASN_ERR_OK) { 311135f7de5SShteryana Shopova snmp_error("cannot decode msg engine boots"); 312135f7de5SShteryana Shopova return (ASN_ERR_FAILED); 313135f7de5SShteryana Shopova } 314135f7de5SShteryana Shopova 315135f7de5SShteryana Shopova if (asn_get_integer(&tb, &pdu->engine.engine_time) != ASN_ERR_OK) { 316135f7de5SShteryana Shopova snmp_error("cannot decode msg engine time"); 317135f7de5SShteryana Shopova return (ASN_ERR_FAILED); 318135f7de5SShteryana Shopova } 319135f7de5SShteryana Shopova 320135f7de5SShteryana Shopova octs_len = SNMP_ADM_STR32_SIZ - 1; 321135f7de5SShteryana Shopova if (asn_get_octetstring(&tb, (u_char *)&pdu->user.sec_name, &octs_len) 322135f7de5SShteryana Shopova != ASN_ERR_OK) { 323135f7de5SShteryana Shopova snmp_error("cannot decode msg user name"); 324135f7de5SShteryana Shopova return (ASN_ERR_FAILED); 325135f7de5SShteryana Shopova } 326135f7de5SShteryana Shopova pdu->user.sec_name[octs_len] = '\0'; 327135f7de5SShteryana Shopova 328135f7de5SShteryana Shopova octs_len = sizeof(pdu->msg_digest); 329135f7de5SShteryana Shopova if (asn_get_octetstring(&tb, (u_char *)&pdu->msg_digest, &octs_len) != 330135f7de5SShteryana Shopova ASN_ERR_OK || ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0 && 331135f7de5SShteryana Shopova octs_len != sizeof(pdu->msg_digest))) { 332135f7de5SShteryana Shopova snmp_error("cannot decode msg authentication param"); 333135f7de5SShteryana Shopova return (ASN_ERR_FAILED); 334135f7de5SShteryana Shopova } 335135f7de5SShteryana Shopova 336135f7de5SShteryana Shopova octs_len = sizeof(pdu->msg_salt); 337135f7de5SShteryana Shopova if (asn_get_octetstring(&tb, (u_char *)&pdu->msg_salt, &octs_len) != 338135f7de5SShteryana Shopova ASN_ERR_OK ||((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0 && 339135f7de5SShteryana Shopova octs_len != sizeof(pdu->msg_salt))) { 340135f7de5SShteryana Shopova snmp_error("cannot decode msg authentication param"); 341135f7de5SShteryana Shopova return (ASN_ERR_FAILED); 342135f7de5SShteryana Shopova } 343135f7de5SShteryana Shopova 344135f7de5SShteryana Shopova if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) { 345135f7de5SShteryana Shopova pdu->digest_ptr = b->asn_ptr - SNMP_USM_AUTH_SIZE; 346135f7de5SShteryana Shopova pdu->digest_ptr -= octs_len + ASN_MAXLENLEN; 347135f7de5SShteryana Shopova } 348f06ca4afSHartmut Brandt 349f06ca4afSHartmut Brandt return (ASN_ERR_OK); 350f06ca4afSHartmut Brandt } 351f06ca4afSHartmut Brandt 352135f7de5SShteryana Shopova static enum snmp_code 353135f7de5SShteryana Shopova pdu_encode_secparams(struct asn_buf *b, struct snmp_pdu *pdu) 354f06ca4afSHartmut Brandt { 355135f7de5SShteryana Shopova u_char buf[256], *sptr; 356135f7de5SShteryana Shopova struct asn_buf tb; 357135f7de5SShteryana Shopova size_t auth_off, moved = 0; 358f06ca4afSHartmut Brandt 359135f7de5SShteryana Shopova auth_off = 0; 360135f7de5SShteryana Shopova memset(buf, 0, 256); 361135f7de5SShteryana Shopova tb.asn_ptr = buf; 362135f7de5SShteryana Shopova tb.asn_len = 256; 363f06ca4afSHartmut Brandt 364135f7de5SShteryana Shopova if (asn_put_temp_header(&tb, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED), 365135f7de5SShteryana Shopova &sptr) != ASN_ERR_OK) 366135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 367f06ca4afSHartmut Brandt 368135f7de5SShteryana Shopova if (asn_put_octetstring(&tb, (u_char *)pdu->engine.engine_id, 369135f7de5SShteryana Shopova pdu->engine.engine_len) != ASN_ERR_OK) 370135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 371f06ca4afSHartmut Brandt 372135f7de5SShteryana Shopova if (asn_put_integer(&tb, pdu->engine.engine_boots) != ASN_ERR_OK) 373135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 374f06ca4afSHartmut Brandt 375135f7de5SShteryana Shopova if (asn_put_integer(&tb, pdu->engine.engine_time) != ASN_ERR_OK) 376135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 377f06ca4afSHartmut Brandt 378135f7de5SShteryana Shopova if (asn_put_octetstring(&tb, (u_char *)pdu->user.sec_name, 379135f7de5SShteryana Shopova strlen(pdu->user.sec_name)) != ASN_ERR_OK) 380135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 381135f7de5SShteryana Shopova 382135f7de5SShteryana Shopova if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) { 383135f7de5SShteryana Shopova auth_off = sizeof(buf) - tb.asn_len + ASN_MAXLENLEN; 384135f7de5SShteryana Shopova if (asn_put_octetstring(&tb, (u_char *)pdu->msg_digest, 385135f7de5SShteryana Shopova sizeof(pdu->msg_digest)) != ASN_ERR_OK) 386135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 387135f7de5SShteryana Shopova } else { 388135f7de5SShteryana Shopova if (asn_put_octetstring(&tb, (u_char *)pdu->msg_digest, 0) 389135f7de5SShteryana Shopova != ASN_ERR_OK) 390135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 391135f7de5SShteryana Shopova } 392135f7de5SShteryana Shopova 393135f7de5SShteryana Shopova if ((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0) { 394135f7de5SShteryana Shopova if (asn_put_octetstring(&tb, (u_char *)pdu->msg_salt, 395135f7de5SShteryana Shopova sizeof(pdu->msg_salt)) != ASN_ERR_OK) 396135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 397135f7de5SShteryana Shopova } else { 398135f7de5SShteryana Shopova if (asn_put_octetstring(&tb, (u_char *)pdu->msg_salt, 0) 399135f7de5SShteryana Shopova != ASN_ERR_OK) 400135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 401135f7de5SShteryana Shopova } 402135f7de5SShteryana Shopova 403135f7de5SShteryana Shopova if (asn_commit_header(&tb, sptr, &moved) != ASN_ERR_OK) 404135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 405135f7de5SShteryana Shopova 406135f7de5SShteryana Shopova if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) 407135f7de5SShteryana Shopova pdu->digest_ptr = b->asn_ptr + auth_off - moved; 408135f7de5SShteryana Shopova 409135f7de5SShteryana Shopova if (asn_put_octetstring(b, buf, sizeof(buf) - tb.asn_len) != ASN_ERR_OK) 410135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 411135f7de5SShteryana Shopova pdu->digest_ptr += ASN_MAXLENLEN; 412135f7de5SShteryana Shopova 413135f7de5SShteryana Shopova if ((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0 && asn_put_temp_header(b, 414135f7de5SShteryana Shopova ASN_TYPE_OCTETSTRING, &pdu->encrypted_ptr) != ASN_ERR_OK) 415135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 416135f7de5SShteryana Shopova 417135f7de5SShteryana Shopova return (SNMP_CODE_OK); 418f06ca4afSHartmut Brandt } 419f06ca4afSHartmut Brandt 420f06ca4afSHartmut Brandt /* 421f06ca4afSHartmut Brandt * Decode the PDU except for the variable bindings itself. 422f06ca4afSHartmut Brandt * If decoding fails because of a bad binding, but the rest can be 423f06ca4afSHartmut Brandt * decoded, ip points to the index of the failed variable (errors 424f06ca4afSHartmut Brandt * OORANGE, BADLEN or BADVERS). 425f06ca4afSHartmut Brandt */ 426f06ca4afSHartmut Brandt enum snmp_code 427f06ca4afSHartmut Brandt snmp_pdu_decode(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip) 428f06ca4afSHartmut Brandt { 429135f7de5SShteryana Shopova enum snmp_code code; 430135f7de5SShteryana Shopova 431135f7de5SShteryana Shopova if ((code = snmp_pdu_decode_header(b, pdu)) != SNMP_CODE_OK) 432135f7de5SShteryana Shopova return (code); 433135f7de5SShteryana Shopova 434135f7de5SShteryana Shopova if (pdu->version == SNMP_V3) { 435135f7de5SShteryana Shopova if (pdu->security_model != SNMP_SECMODEL_USM) 436135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 437135f7de5SShteryana Shopova if ((code = snmp_pdu_decode_secmode(b, pdu)) != SNMP_CODE_OK) 438135f7de5SShteryana Shopova return (code); 439135f7de5SShteryana Shopova } 440135f7de5SShteryana Shopova 441135f7de5SShteryana Shopova code = snmp_pdu_decode_scoped(b, pdu, ip); 442135f7de5SShteryana Shopova 443135f7de5SShteryana Shopova switch (code) { 444135f7de5SShteryana Shopova case SNMP_CODE_FAILED: 445135f7de5SShteryana Shopova snmp_pdu_free(pdu); 446135f7de5SShteryana Shopova break; 447135f7de5SShteryana Shopova 448135f7de5SShteryana Shopova case SNMP_CODE_BADENC: 449135f7de5SShteryana Shopova if (pdu->version == SNMP_Verr) 450135f7de5SShteryana Shopova return (SNMP_CODE_BADVERS); 451135f7de5SShteryana Shopova 452135f7de5SShteryana Shopova default: 453135f7de5SShteryana Shopova break; 454135f7de5SShteryana Shopova } 455135f7de5SShteryana Shopova 456135f7de5SShteryana Shopova return (code); 457135f7de5SShteryana Shopova } 458135f7de5SShteryana Shopova 459135f7de5SShteryana Shopova enum snmp_code 460135f7de5SShteryana Shopova snmp_pdu_decode_header(struct asn_buf *b, struct snmp_pdu *pdu) 461135f7de5SShteryana Shopova { 462135f7de5SShteryana Shopova int32_t version; 463135f7de5SShteryana Shopova u_int octs_len; 464f06ca4afSHartmut Brandt asn_len_t len; 465f06ca4afSHartmut Brandt 466135f7de5SShteryana Shopova pdu->outer_ptr = b->asn_ptr; 467135f7de5SShteryana Shopova pdu->outer_len = b->asn_len; 468f06ca4afSHartmut Brandt 469f06ca4afSHartmut Brandt if (asn_get_sequence(b, &len) != ASN_ERR_OK) { 470f06ca4afSHartmut Brandt snmp_error("cannot decode pdu header"); 471f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED); 472f06ca4afSHartmut Brandt } 473f06ca4afSHartmut Brandt if (b->asn_len < len) { 474f06ca4afSHartmut Brandt snmp_error("outer sequence value too short"); 475f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED); 476f06ca4afSHartmut Brandt } 477f06ca4afSHartmut Brandt if (b->asn_len != len) { 478f06ca4afSHartmut Brandt snmp_error("ignoring trailing junk in message"); 479f06ca4afSHartmut Brandt b->asn_len = len; 480f06ca4afSHartmut Brandt } 481f06ca4afSHartmut Brandt 482135f7de5SShteryana Shopova if (asn_get_integer(b, &version) != ASN_ERR_OK) { 483135f7de5SShteryana Shopova snmp_error("cannot decode version"); 484f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED); 485135f7de5SShteryana Shopova } 486f06ca4afSHartmut Brandt 487135f7de5SShteryana Shopova if (version == 0) 488135f7de5SShteryana Shopova pdu->version = SNMP_V1; 489135f7de5SShteryana Shopova else if (version == 1) 490135f7de5SShteryana Shopova pdu->version = SNMP_V2c; 491135f7de5SShteryana Shopova else if (version == 3) 492135f7de5SShteryana Shopova pdu->version = SNMP_V3; 493135f7de5SShteryana Shopova else { 494135f7de5SShteryana Shopova pdu->version = SNMP_Verr; 495135f7de5SShteryana Shopova snmp_error("unsupported SNMP version"); 496f06ca4afSHartmut Brandt return (SNMP_CODE_BADENC); 497f06ca4afSHartmut Brandt } 498f06ca4afSHartmut Brandt 499135f7de5SShteryana Shopova if (pdu->version == SNMP_V3) { 500135f7de5SShteryana Shopova if (asn_get_sequence(b, &len) != ASN_ERR_OK) { 501135f7de5SShteryana Shopova snmp_error("cannot decode pdu global data header"); 502135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 503135f7de5SShteryana Shopova } 504135f7de5SShteryana Shopova 505135f7de5SShteryana Shopova if (asn_get_integer(b, &pdu->identifier) != ASN_ERR_OK) { 506135f7de5SShteryana Shopova snmp_error("cannot decode msg indetifier"); 507135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 508135f7de5SShteryana Shopova } 509135f7de5SShteryana Shopova 510135f7de5SShteryana Shopova if (asn_get_integer(b, &pdu->engine.max_msg_size) 511135f7de5SShteryana Shopova != ASN_ERR_OK) { 512135f7de5SShteryana Shopova snmp_error("cannot decode msg size"); 513135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 514135f7de5SShteryana Shopova } 515135f7de5SShteryana Shopova 516135f7de5SShteryana Shopova octs_len = 1; 517135f7de5SShteryana Shopova if (asn_get_octetstring(b, (u_char *)&pdu->flags, 518135f7de5SShteryana Shopova &octs_len) != ASN_ERR_OK) { 519135f7de5SShteryana Shopova snmp_error("cannot decode msg flags"); 520135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 521135f7de5SShteryana Shopova } 522135f7de5SShteryana Shopova 523135f7de5SShteryana Shopova if (asn_get_integer(b, &pdu->security_model) != ASN_ERR_OK) { 524135f7de5SShteryana Shopova snmp_error("cannot decode msg size"); 525135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 526135f7de5SShteryana Shopova } 527135f7de5SShteryana Shopova 528135f7de5SShteryana Shopova if (pdu->security_model != SNMP_SECMODEL_USM) 529135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 530135f7de5SShteryana Shopova 531135f7de5SShteryana Shopova if (parse_secparams(b, pdu) != ASN_ERR_OK) 532135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 533135f7de5SShteryana Shopova } else { 534135f7de5SShteryana Shopova octs_len = SNMP_COMMUNITY_MAXLEN; 535135f7de5SShteryana Shopova if (asn_get_octetstring(b, (u_char *)pdu->community, 536135f7de5SShteryana Shopova &octs_len) != ASN_ERR_OK) { 537135f7de5SShteryana Shopova snmp_error("cannot decode community"); 538135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 539135f7de5SShteryana Shopova } 540135f7de5SShteryana Shopova pdu->community[octs_len] = '\0'; 541135f7de5SShteryana Shopova } 542135f7de5SShteryana Shopova 543f06ca4afSHartmut Brandt return (SNMP_CODE_OK); 544f06ca4afSHartmut Brandt } 545f06ca4afSHartmut Brandt 546135f7de5SShteryana Shopova enum snmp_code 547135f7de5SShteryana Shopova snmp_pdu_decode_scoped(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip) 548135f7de5SShteryana Shopova { 549135f7de5SShteryana Shopova u_char type; 550135f7de5SShteryana Shopova asn_len_t len, trailer; 551135f7de5SShteryana Shopova enum asn_err err; 552135f7de5SShteryana Shopova 553135f7de5SShteryana Shopova if (pdu->version == SNMP_V3) { 554135f7de5SShteryana Shopova if (asn_get_sequence(b, &len) != ASN_ERR_OK) { 555135f7de5SShteryana Shopova snmp_error("cannot decode scoped pdu header"); 556135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 557135f7de5SShteryana Shopova } 558135f7de5SShteryana Shopova 559135f7de5SShteryana Shopova len = SNMP_ENGINE_ID_SIZ; 560135f7de5SShteryana Shopova if (asn_get_octetstring(b, (u_char *)&pdu->context_engine, 561135f7de5SShteryana Shopova &len) != ASN_ERR_OK) { 562135f7de5SShteryana Shopova snmp_error("cannot decode msg context engine"); 563135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 564135f7de5SShteryana Shopova } 565135f7de5SShteryana Shopova pdu->context_engine_len = len; 566135f7de5SShteryana Shopova 567135f7de5SShteryana Shopova len = SNMP_CONTEXT_NAME_SIZ; 568135f7de5SShteryana Shopova if (asn_get_octetstring(b, (u_char *)&pdu->context_name, 569135f7de5SShteryana Shopova &len) != ASN_ERR_OK) { 570135f7de5SShteryana Shopova snmp_error("cannot decode msg context name"); 571135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 572135f7de5SShteryana Shopova } 573135f7de5SShteryana Shopova pdu->context_name[len] = '\0'; 574135f7de5SShteryana Shopova } 575135f7de5SShteryana Shopova 576135f7de5SShteryana Shopova if (asn_get_header(b, &type, &len) != ASN_ERR_OK) { 577135f7de5SShteryana Shopova snmp_error("cannot get pdu header"); 578135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 579135f7de5SShteryana Shopova } 580135f7de5SShteryana Shopova if ((type & ~ASN_TYPE_MASK) != 581135f7de5SShteryana Shopova (ASN_TYPE_CONSTRUCTED | ASN_CLASS_CONTEXT)) { 582135f7de5SShteryana Shopova snmp_error("bad pdu header tag"); 583135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 584135f7de5SShteryana Shopova } 585135f7de5SShteryana Shopova pdu->type = type & ASN_TYPE_MASK; 586135f7de5SShteryana Shopova 587135f7de5SShteryana Shopova switch (pdu->type) { 588135f7de5SShteryana Shopova 589135f7de5SShteryana Shopova case SNMP_PDU_GET: 590135f7de5SShteryana Shopova case SNMP_PDU_GETNEXT: 591135f7de5SShteryana Shopova case SNMP_PDU_RESPONSE: 592135f7de5SShteryana Shopova case SNMP_PDU_SET: 593135f7de5SShteryana Shopova break; 594135f7de5SShteryana Shopova 595135f7de5SShteryana Shopova case SNMP_PDU_TRAP: 596135f7de5SShteryana Shopova if (pdu->version != SNMP_V1) { 597135f7de5SShteryana Shopova snmp_error("bad pdu type %u", pdu->type); 598135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 599135f7de5SShteryana Shopova } 600135f7de5SShteryana Shopova break; 601135f7de5SShteryana Shopova 602135f7de5SShteryana Shopova case SNMP_PDU_GETBULK: 603135f7de5SShteryana Shopova case SNMP_PDU_INFORM: 604135f7de5SShteryana Shopova case SNMP_PDU_TRAP2: 605135f7de5SShteryana Shopova case SNMP_PDU_REPORT: 606135f7de5SShteryana Shopova if (pdu->version == SNMP_V1) { 607135f7de5SShteryana Shopova snmp_error("bad pdu type %u", pdu->type); 608135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 609135f7de5SShteryana Shopova } 610135f7de5SShteryana Shopova break; 611135f7de5SShteryana Shopova 612135f7de5SShteryana Shopova default: 613135f7de5SShteryana Shopova snmp_error("bad pdu type %u", pdu->type); 614135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 615135f7de5SShteryana Shopova } 616135f7de5SShteryana Shopova 617135f7de5SShteryana Shopova trailer = b->asn_len - len; 618135f7de5SShteryana Shopova b->asn_len = len; 619135f7de5SShteryana Shopova 620135f7de5SShteryana Shopova err = parse_pdus(b, pdu, ip); 621135f7de5SShteryana Shopova if (ASN_ERR_STOPPED(err)) 622135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 623135f7de5SShteryana Shopova 624135f7de5SShteryana Shopova if (b->asn_len != 0) 625135f7de5SShteryana Shopova snmp_error("ignoring trailing junk after pdu"); 626135f7de5SShteryana Shopova 627135f7de5SShteryana Shopova b->asn_len = trailer; 628135f7de5SShteryana Shopova 629135f7de5SShteryana Shopova return (SNMP_CODE_OK); 630135f7de5SShteryana Shopova } 631135f7de5SShteryana Shopova 632135f7de5SShteryana Shopova enum snmp_code 633135f7de5SShteryana Shopova snmp_pdu_decode_secmode(struct asn_buf *b, struct snmp_pdu *pdu) 634135f7de5SShteryana Shopova { 635135f7de5SShteryana Shopova u_char type; 636135f7de5SShteryana Shopova enum snmp_code code; 637135f7de5SShteryana Shopova uint8_t digest[SNMP_USM_AUTH_SIZE]; 638135f7de5SShteryana Shopova 639135f7de5SShteryana Shopova if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH && 640135f7de5SShteryana Shopova (pdu->flags & SNMP_MSG_AUTH_FLAG) == 0) 641135f7de5SShteryana Shopova return (SNMP_CODE_BADSECLEVEL); 642135f7de5SShteryana Shopova 643*2b802662SShteryana Shopova if ((code = snmp_pdu_calc_digest(pdu, digest)) != 644135f7de5SShteryana Shopova SNMP_CODE_OK) 645135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 646135f7de5SShteryana Shopova 647135f7de5SShteryana Shopova if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH && 648135f7de5SShteryana Shopova memcmp(digest, pdu->msg_digest, sizeof(pdu->msg_digest)) != 0) 649135f7de5SShteryana Shopova return (SNMP_CODE_BADDIGEST); 650135f7de5SShteryana Shopova 651135f7de5SShteryana Shopova if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV && (asn_get_header(b, &type, 652135f7de5SShteryana Shopova &pdu->scoped_len) != ASN_ERR_OK || type != ASN_TYPE_OCTETSTRING)) { 653135f7de5SShteryana Shopova snmp_error("cannot decode encrypted pdu"); 654135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 655135f7de5SShteryana Shopova } 656135f7de5SShteryana Shopova pdu->scoped_ptr = b->asn_ptr; 657135f7de5SShteryana Shopova 658135f7de5SShteryana Shopova if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV && 659135f7de5SShteryana Shopova (pdu->flags & SNMP_MSG_PRIV_FLAG) == 0) 660135f7de5SShteryana Shopova return (SNMP_CODE_BADSECLEVEL); 661135f7de5SShteryana Shopova 662*2b802662SShteryana Shopova if ((code = snmp_pdu_decrypt(pdu)) != SNMP_CODE_OK) 663135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 664135f7de5SShteryana Shopova 665135f7de5SShteryana Shopova return (code); 666135f7de5SShteryana Shopova } 667135f7de5SShteryana Shopova 668f06ca4afSHartmut Brandt /* 66970af00a1SHartmut Brandt * Check whether what we have is the complete PDU by snooping at the 67070af00a1SHartmut Brandt * enclosing structure header. This returns: 67170af00a1SHartmut Brandt * -1 if there are ASN.1 errors 67270af00a1SHartmut Brandt * 0 if we need more data 67370af00a1SHartmut Brandt * > 0 the length of this PDU 67470af00a1SHartmut Brandt */ 67570af00a1SHartmut Brandt int 67670af00a1SHartmut Brandt snmp_pdu_snoop(const struct asn_buf *b0) 67770af00a1SHartmut Brandt { 67870af00a1SHartmut Brandt u_int length; 67970af00a1SHartmut Brandt asn_len_t len; 68070af00a1SHartmut Brandt struct asn_buf b = *b0; 68170af00a1SHartmut Brandt 68270af00a1SHartmut Brandt /* <0x10|0x20> <len> <data...> */ 68370af00a1SHartmut Brandt 68470af00a1SHartmut Brandt if (b.asn_len == 0) 68570af00a1SHartmut Brandt return (0); 68670af00a1SHartmut Brandt if (b.asn_cptr[0] != (ASN_TYPE_SEQUENCE | ASN_TYPE_CONSTRUCTED)) { 68770af00a1SHartmut Brandt asn_error(&b, "bad sequence type %u", b.asn_cptr[0]); 68870af00a1SHartmut Brandt return (-1); 68970af00a1SHartmut Brandt } 69070af00a1SHartmut Brandt b.asn_len--; 69170af00a1SHartmut Brandt b.asn_cptr++; 69270af00a1SHartmut Brandt 69370af00a1SHartmut Brandt if (b.asn_len == 0) 69470af00a1SHartmut Brandt return (0); 69570af00a1SHartmut Brandt 69670af00a1SHartmut Brandt if (*b.asn_cptr & 0x80) { 69770af00a1SHartmut Brandt /* long length */ 69870af00a1SHartmut Brandt length = *b.asn_cptr++ & 0x7f; 69970af00a1SHartmut Brandt b.asn_len--; 70070af00a1SHartmut Brandt if (length == 0) { 70170af00a1SHartmut Brandt asn_error(&b, "indefinite length not supported"); 70270af00a1SHartmut Brandt return (-1); 70370af00a1SHartmut Brandt } 70470af00a1SHartmut Brandt if (length > ASN_MAXLENLEN) { 70570af00a1SHartmut Brandt asn_error(&b, "long length too long (%u)", length); 70670af00a1SHartmut Brandt return (-1); 70770af00a1SHartmut Brandt } 70870af00a1SHartmut Brandt if (length > b.asn_len) 70970af00a1SHartmut Brandt return (0); 71070af00a1SHartmut Brandt len = 0; 71170af00a1SHartmut Brandt while (length--) { 71270af00a1SHartmut Brandt len = (len << 8) | *b.asn_cptr++; 71370af00a1SHartmut Brandt b.asn_len--; 71470af00a1SHartmut Brandt } 71570af00a1SHartmut Brandt } else { 71670af00a1SHartmut Brandt len = *b.asn_cptr++; 71770af00a1SHartmut Brandt b.asn_len--; 71870af00a1SHartmut Brandt } 71970af00a1SHartmut Brandt 72070af00a1SHartmut Brandt if (len > b.asn_len) 72170af00a1SHartmut Brandt return (0); 72270af00a1SHartmut Brandt 72370af00a1SHartmut Brandt return (len + b.asn_cptr - b0->asn_cptr); 72470af00a1SHartmut Brandt } 72570af00a1SHartmut Brandt 72670af00a1SHartmut Brandt /* 727f06ca4afSHartmut Brandt * Encode the SNMP PDU without the variable bindings field. 728f06ca4afSHartmut Brandt * We do this the rather uneffective way by 729f06ca4afSHartmut Brandt * moving things around and assuming that the length field will never 730f06ca4afSHartmut Brandt * use more than 2 bytes. 731f06ca4afSHartmut Brandt * We need a number of pointers to apply the fixes afterwards. 732f06ca4afSHartmut Brandt */ 733f06ca4afSHartmut Brandt enum snmp_code 734f06ca4afSHartmut Brandt snmp_pdu_encode_header(struct asn_buf *b, struct snmp_pdu *pdu) 735f06ca4afSHartmut Brandt { 736f06ca4afSHartmut Brandt enum asn_err err; 737135f7de5SShteryana Shopova u_char *v3_hdr_ptr; 738f06ca4afSHartmut Brandt 739f06ca4afSHartmut Brandt if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED), 740f06ca4afSHartmut Brandt &pdu->outer_ptr) != ASN_ERR_OK) 741f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED); 742f06ca4afSHartmut Brandt 743f06ca4afSHartmut Brandt if (pdu->version == SNMP_V1) 744f06ca4afSHartmut Brandt err = asn_put_integer(b, 0); 745f06ca4afSHartmut Brandt else if (pdu->version == SNMP_V2c) 746f06ca4afSHartmut Brandt err = asn_put_integer(b, 1); 747135f7de5SShteryana Shopova else if (pdu->version == SNMP_V3) 748135f7de5SShteryana Shopova err = asn_put_integer(b, 3); 749f06ca4afSHartmut Brandt else 750f06ca4afSHartmut Brandt return (SNMP_CODE_BADVERS); 751f06ca4afSHartmut Brandt if (err != ASN_ERR_OK) 752f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED); 753f06ca4afSHartmut Brandt 754135f7de5SShteryana Shopova if (pdu->version == SNMP_V3) { 755135f7de5SShteryana Shopova if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE | 756135f7de5SShteryana Shopova ASN_TYPE_CONSTRUCTED), &v3_hdr_ptr) != ASN_ERR_OK) 757135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 758135f7de5SShteryana Shopova 759135f7de5SShteryana Shopova if (asn_put_integer(b, pdu->identifier) != ASN_ERR_OK) 760135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 761135f7de5SShteryana Shopova 762135f7de5SShteryana Shopova if (asn_put_integer(b, pdu->engine.max_msg_size) != ASN_ERR_OK) 763135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 764135f7de5SShteryana Shopova 765135f7de5SShteryana Shopova if (pdu->type != SNMP_PDU_RESPONSE && 766135f7de5SShteryana Shopova pdu->type != SNMP_PDU_TRAP && 767135f7de5SShteryana Shopova pdu->type != SNMP_PDU_REPORT) 768135f7de5SShteryana Shopova pdu->flags |= SNMP_MSG_REPORT_FLAG; 769135f7de5SShteryana Shopova 770135f7de5SShteryana Shopova if (asn_put_octetstring(b, (u_char *)&pdu->flags, 1) 771135f7de5SShteryana Shopova != ASN_ERR_OK) 772135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 773135f7de5SShteryana Shopova 774135f7de5SShteryana Shopova if (asn_put_integer(b, pdu->security_model) != ASN_ERR_OK) 775135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 776135f7de5SShteryana Shopova 777135f7de5SShteryana Shopova if (asn_commit_header(b, v3_hdr_ptr, NULL) != ASN_ERR_OK) 778135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 779135f7de5SShteryana Shopova 780135f7de5SShteryana Shopova if (pdu->security_model != SNMP_SECMODEL_USM) 781135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 782135f7de5SShteryana Shopova 783135f7de5SShteryana Shopova if (pdu_encode_secparams(b, pdu) != SNMP_CODE_OK) 784135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 785135f7de5SShteryana Shopova 786135f7de5SShteryana Shopova /* View-based Access Conntrol information */ 787135f7de5SShteryana Shopova if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE | 788135f7de5SShteryana Shopova ASN_TYPE_CONSTRUCTED), &pdu->scoped_ptr) != ASN_ERR_OK) 789135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 790135f7de5SShteryana Shopova 791135f7de5SShteryana Shopova if (asn_put_octetstring(b, (u_char *)pdu->context_engine, 792135f7de5SShteryana Shopova pdu->context_engine_len) != ASN_ERR_OK) 793135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 794135f7de5SShteryana Shopova 795135f7de5SShteryana Shopova if (asn_put_octetstring(b, (u_char *)pdu->context_name, 796135f7de5SShteryana Shopova strlen(pdu->context_name)) != ASN_ERR_OK) 797135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 798135f7de5SShteryana Shopova } else { 799f06ca4afSHartmut Brandt if (asn_put_octetstring(b, (u_char *)pdu->community, 800f06ca4afSHartmut Brandt strlen(pdu->community)) != ASN_ERR_OK) 801f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED); 802135f7de5SShteryana Shopova } 803f06ca4afSHartmut Brandt 804f06ca4afSHartmut Brandt if (asn_put_temp_header(b, (ASN_TYPE_CONSTRUCTED | ASN_CLASS_CONTEXT | 805f06ca4afSHartmut Brandt pdu->type), &pdu->pdu_ptr) != ASN_ERR_OK) 806f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED); 807f06ca4afSHartmut Brandt 808f06ca4afSHartmut Brandt if (pdu->type == SNMP_PDU_TRAP) { 809f06ca4afSHartmut Brandt if (pdu->version != SNMP_V1 || 810f06ca4afSHartmut Brandt asn_put_objid(b, &pdu->enterprise) != ASN_ERR_OK || 811f06ca4afSHartmut Brandt asn_put_ipaddress(b, pdu->agent_addr) != ASN_ERR_OK || 812f06ca4afSHartmut Brandt asn_put_integer(b, pdu->generic_trap) != ASN_ERR_OK || 813f06ca4afSHartmut Brandt asn_put_integer(b, pdu->specific_trap) != ASN_ERR_OK || 814f06ca4afSHartmut Brandt asn_put_timeticks(b, pdu->time_stamp) != ASN_ERR_OK) 815f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED); 816f06ca4afSHartmut Brandt } else { 817f06ca4afSHartmut Brandt if (pdu->version == SNMP_V1 && (pdu->type == SNMP_PDU_GETBULK || 818f06ca4afSHartmut Brandt pdu->type == SNMP_PDU_INFORM || 819f06ca4afSHartmut Brandt pdu->type == SNMP_PDU_TRAP2 || 820f06ca4afSHartmut Brandt pdu->type == SNMP_PDU_REPORT)) 821f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED); 822f06ca4afSHartmut Brandt 823f06ca4afSHartmut Brandt if (asn_put_integer(b, pdu->request_id) != ASN_ERR_OK || 824f06ca4afSHartmut Brandt asn_put_integer(b, pdu->error_status) != ASN_ERR_OK || 825f06ca4afSHartmut Brandt asn_put_integer(b, pdu->error_index) != ASN_ERR_OK) 826f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED); 827f06ca4afSHartmut Brandt } 828f06ca4afSHartmut Brandt 829f06ca4afSHartmut Brandt if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED), 830f06ca4afSHartmut Brandt &pdu->vars_ptr) != ASN_ERR_OK) 831f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED); 832f06ca4afSHartmut Brandt 833f06ca4afSHartmut Brandt return (SNMP_CODE_OK); 834f06ca4afSHartmut Brandt } 835f06ca4afSHartmut Brandt 836135f7de5SShteryana Shopova static enum asn_err 837135f7de5SShteryana Shopova snmp_pdu_fix_padd(struct asn_buf *b, struct snmp_pdu *pdu) 838f06ca4afSHartmut Brandt { 839135f7de5SShteryana Shopova asn_len_t padlen; 840135f7de5SShteryana Shopova 841135f7de5SShteryana Shopova if (pdu->user.priv_proto == SNMP_PRIV_DES && pdu->scoped_len % 8 != 0) { 842135f7de5SShteryana Shopova padlen = 8 - (pdu->scoped_len % 8); 843135f7de5SShteryana Shopova if (asn_pad(b, padlen) != ASN_ERR_OK) 844135f7de5SShteryana Shopova return (ASN_ERR_FAILED); 845135f7de5SShteryana Shopova pdu->scoped_len += padlen; 846135f7de5SShteryana Shopova } 847135f7de5SShteryana Shopova 848135f7de5SShteryana Shopova return (ASN_ERR_OK); 849135f7de5SShteryana Shopova } 850135f7de5SShteryana Shopova 851135f7de5SShteryana Shopova enum snmp_code 852135f7de5SShteryana Shopova snmp_fix_encoding(struct asn_buf *b, struct snmp_pdu *pdu) 853135f7de5SShteryana Shopova { 854135f7de5SShteryana Shopova size_t moved = 0; 855135f7de5SShteryana Shopova enum snmp_code code; 856135f7de5SShteryana Shopova 857135f7de5SShteryana Shopova if (asn_commit_header(b, pdu->vars_ptr, NULL) != ASN_ERR_OK || 858135f7de5SShteryana Shopova asn_commit_header(b, pdu->pdu_ptr, NULL) != ASN_ERR_OK) 859f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED); 860135f7de5SShteryana Shopova 861135f7de5SShteryana Shopova if (pdu->version == SNMP_V3) { 862135f7de5SShteryana Shopova if (asn_commit_header(b, pdu->scoped_ptr, NULL) != ASN_ERR_OK) 863135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 864135f7de5SShteryana Shopova 865135f7de5SShteryana Shopova pdu->scoped_len = b->asn_ptr - pdu->scoped_ptr; 866135f7de5SShteryana Shopova if ((code = snmp_pdu_fix_padd(b, pdu))!= ASN_ERR_OK) 867135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 868135f7de5SShteryana Shopova 869135f7de5SShteryana Shopova if (pdu->security_model != SNMP_SECMODEL_USM) 870135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 871135f7de5SShteryana Shopova 872*2b802662SShteryana Shopova if (snmp_pdu_encrypt(pdu) != SNMP_CODE_OK) 873135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 874135f7de5SShteryana Shopova 875135f7de5SShteryana Shopova if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV && 876135f7de5SShteryana Shopova asn_commit_header(b, pdu->encrypted_ptr, NULL) != ASN_ERR_OK) 877135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 878135f7de5SShteryana Shopova } 879135f7de5SShteryana Shopova 880135f7de5SShteryana Shopova if (asn_commit_header(b, pdu->outer_ptr, &moved) != ASN_ERR_OK) 881135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 882135f7de5SShteryana Shopova 883135f7de5SShteryana Shopova pdu->outer_len = b->asn_ptr - pdu->outer_ptr; 884135f7de5SShteryana Shopova pdu->digest_ptr -= moved; 885135f7de5SShteryana Shopova 886135f7de5SShteryana Shopova if (pdu->version == SNMP_V3) { 887*2b802662SShteryana Shopova if ((code = snmp_pdu_calc_digest(pdu, pdu->msg_digest)) != 888135f7de5SShteryana Shopova SNMP_CODE_OK) 889135f7de5SShteryana Shopova return (SNMP_CODE_FAILED); 890135f7de5SShteryana Shopova 891135f7de5SShteryana Shopova if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) 892135f7de5SShteryana Shopova memcpy(pdu->digest_ptr, pdu->msg_digest, 893135f7de5SShteryana Shopova sizeof(pdu->msg_digest)); 894135f7de5SShteryana Shopova } 895135f7de5SShteryana Shopova 896f06ca4afSHartmut Brandt return (SNMP_CODE_OK); 897f06ca4afSHartmut Brandt } 898f06ca4afSHartmut Brandt 899f06ca4afSHartmut Brandt /* 900f06ca4afSHartmut Brandt * Encode a binding. Caller must ensure, that the syntax is ok for that version. 901f06ca4afSHartmut Brandt * Be sure not to cobber b, when something fails. 902f06ca4afSHartmut Brandt */ 903f06ca4afSHartmut Brandt enum asn_err 904f06ca4afSHartmut Brandt snmp_binding_encode(struct asn_buf *b, const struct snmp_value *binding) 905f06ca4afSHartmut Brandt { 906f06ca4afSHartmut Brandt u_char *ptr; 907f06ca4afSHartmut Brandt enum asn_err err; 908f06ca4afSHartmut Brandt struct asn_buf save = *b; 909f06ca4afSHartmut Brandt 910f06ca4afSHartmut Brandt if ((err = asn_put_temp_header(b, (ASN_TYPE_SEQUENCE | 911f06ca4afSHartmut Brandt ASN_TYPE_CONSTRUCTED), &ptr)) != ASN_ERR_OK) { 912f06ca4afSHartmut Brandt *b = save; 913f06ca4afSHartmut Brandt return (err); 914f06ca4afSHartmut Brandt } 915f06ca4afSHartmut Brandt 916f06ca4afSHartmut Brandt if ((err = asn_put_objid(b, &binding->var)) != ASN_ERR_OK) { 917f06ca4afSHartmut Brandt *b = save; 918f06ca4afSHartmut Brandt return (err); 919f06ca4afSHartmut Brandt } 920f06ca4afSHartmut Brandt 921f06ca4afSHartmut Brandt switch (binding->syntax) { 922f06ca4afSHartmut Brandt 923f06ca4afSHartmut Brandt case SNMP_SYNTAX_NULL: 924f06ca4afSHartmut Brandt err = asn_put_null(b); 925f06ca4afSHartmut Brandt break; 926f06ca4afSHartmut Brandt 927f06ca4afSHartmut Brandt case SNMP_SYNTAX_INTEGER: 928f06ca4afSHartmut Brandt err = asn_put_integer(b, binding->v.integer); 929f06ca4afSHartmut Brandt break; 930f06ca4afSHartmut Brandt 931f06ca4afSHartmut Brandt case SNMP_SYNTAX_OCTETSTRING: 932f06ca4afSHartmut Brandt err = asn_put_octetstring(b, binding->v.octetstring.octets, 933f06ca4afSHartmut Brandt binding->v.octetstring.len); 934f06ca4afSHartmut Brandt break; 935f06ca4afSHartmut Brandt 936f06ca4afSHartmut Brandt case SNMP_SYNTAX_OID: 937f06ca4afSHartmut Brandt err = asn_put_objid(b, &binding->v.oid); 938f06ca4afSHartmut Brandt break; 939f06ca4afSHartmut Brandt 940f06ca4afSHartmut Brandt case SNMP_SYNTAX_IPADDRESS: 941f06ca4afSHartmut Brandt err = asn_put_ipaddress(b, binding->v.ipaddress); 942f06ca4afSHartmut Brandt break; 943f06ca4afSHartmut Brandt 944f06ca4afSHartmut Brandt case SNMP_SYNTAX_TIMETICKS: 945f06ca4afSHartmut Brandt err = asn_put_uint32(b, ASN_APP_TIMETICKS, binding->v.uint32); 946f06ca4afSHartmut Brandt break; 947f06ca4afSHartmut Brandt 948f06ca4afSHartmut Brandt case SNMP_SYNTAX_COUNTER: 949f06ca4afSHartmut Brandt err = asn_put_uint32(b, ASN_APP_COUNTER, binding->v.uint32); 950f06ca4afSHartmut Brandt break; 951f06ca4afSHartmut Brandt 952f06ca4afSHartmut Brandt case SNMP_SYNTAX_GAUGE: 953f06ca4afSHartmut Brandt err = asn_put_uint32(b, ASN_APP_GAUGE, binding->v.uint32); 954f06ca4afSHartmut Brandt break; 955f06ca4afSHartmut Brandt 956f06ca4afSHartmut Brandt case SNMP_SYNTAX_COUNTER64: 957f06ca4afSHartmut Brandt err = asn_put_counter64(b, binding->v.counter64); 958f06ca4afSHartmut Brandt break; 959f06ca4afSHartmut Brandt 960f06ca4afSHartmut Brandt case SNMP_SYNTAX_NOSUCHOBJECT: 961f06ca4afSHartmut Brandt err = asn_put_exception(b, ASN_EXCEPT_NOSUCHOBJECT); 962f06ca4afSHartmut Brandt break; 963f06ca4afSHartmut Brandt 964f06ca4afSHartmut Brandt case SNMP_SYNTAX_NOSUCHINSTANCE: 965f06ca4afSHartmut Brandt err = asn_put_exception(b, ASN_EXCEPT_NOSUCHINSTANCE); 966f06ca4afSHartmut Brandt break; 967f06ca4afSHartmut Brandt 968f06ca4afSHartmut Brandt case SNMP_SYNTAX_ENDOFMIBVIEW: 969f06ca4afSHartmut Brandt err = asn_put_exception(b, ASN_EXCEPT_ENDOFMIBVIEW); 970f06ca4afSHartmut Brandt break; 971f06ca4afSHartmut Brandt } 972f06ca4afSHartmut Brandt 973f06ca4afSHartmut Brandt if (err != ASN_ERR_OK) { 974f06ca4afSHartmut Brandt *b = save; 975f06ca4afSHartmut Brandt return (err); 976f06ca4afSHartmut Brandt } 977f06ca4afSHartmut Brandt 978135f7de5SShteryana Shopova err = asn_commit_header(b, ptr, NULL); 979f06ca4afSHartmut Brandt if (err != ASN_ERR_OK) { 980f06ca4afSHartmut Brandt *b = save; 981f06ca4afSHartmut Brandt return (err); 982f06ca4afSHartmut Brandt } 983f06ca4afSHartmut Brandt 984f06ca4afSHartmut Brandt return (ASN_ERR_OK); 985f06ca4afSHartmut Brandt } 986f06ca4afSHartmut Brandt 987f06ca4afSHartmut Brandt /* 988f06ca4afSHartmut Brandt * Encode an PDU. 989f06ca4afSHartmut Brandt */ 990f06ca4afSHartmut Brandt enum snmp_code 991f06ca4afSHartmut Brandt snmp_pdu_encode(struct snmp_pdu *pdu, struct asn_buf *resp_b) 992f06ca4afSHartmut Brandt { 993f06ca4afSHartmut Brandt u_int idx; 994f06ca4afSHartmut Brandt enum snmp_code err; 995f06ca4afSHartmut Brandt 996f06ca4afSHartmut Brandt if ((err = snmp_pdu_encode_header(resp_b, pdu)) != SNMP_CODE_OK) 997f06ca4afSHartmut Brandt return (err); 998f06ca4afSHartmut Brandt for (idx = 0; idx < pdu->nbindings; idx++) 999f06ca4afSHartmut Brandt if ((err = snmp_binding_encode(resp_b, &pdu->bindings[idx])) 1000f06ca4afSHartmut Brandt != ASN_ERR_OK) 1001f06ca4afSHartmut Brandt return (SNMP_CODE_FAILED); 1002f06ca4afSHartmut Brandt 1003f06ca4afSHartmut Brandt return (snmp_fix_encoding(resp_b, pdu)); 1004f06ca4afSHartmut Brandt } 1005f06ca4afSHartmut Brandt 1006f06ca4afSHartmut Brandt static void 1007f06ca4afSHartmut Brandt dump_binding(const struct snmp_value *b) 1008f06ca4afSHartmut Brandt { 1009f06ca4afSHartmut Brandt u_int i; 1010f06ca4afSHartmut Brandt char buf[ASN_OIDSTRLEN]; 1011f06ca4afSHartmut Brandt 1012f06ca4afSHartmut Brandt snmp_printf("%s=", asn_oid2str_r(&b->var, buf)); 1013f06ca4afSHartmut Brandt switch (b->syntax) { 1014f06ca4afSHartmut Brandt 1015f06ca4afSHartmut Brandt case SNMP_SYNTAX_NULL: 1016f06ca4afSHartmut Brandt snmp_printf("NULL"); 1017f06ca4afSHartmut Brandt break; 1018f06ca4afSHartmut Brandt 1019f06ca4afSHartmut Brandt case SNMP_SYNTAX_INTEGER: 1020f06ca4afSHartmut Brandt snmp_printf("INTEGER %d", b->v.integer); 1021f06ca4afSHartmut Brandt break; 1022f06ca4afSHartmut Brandt 1023f06ca4afSHartmut Brandt case SNMP_SYNTAX_OCTETSTRING: 1024f06ca4afSHartmut Brandt snmp_printf("OCTET STRING %lu:", b->v.octetstring.len); 1025f06ca4afSHartmut Brandt for (i = 0; i < b->v.octetstring.len; i++) 1026f06ca4afSHartmut Brandt snmp_printf(" %02x", b->v.octetstring.octets[i]); 1027f06ca4afSHartmut Brandt break; 1028f06ca4afSHartmut Brandt 1029f06ca4afSHartmut Brandt case SNMP_SYNTAX_OID: 1030f06ca4afSHartmut Brandt snmp_printf("OID %s", asn_oid2str_r(&b->v.oid, buf)); 1031f06ca4afSHartmut Brandt break; 1032f06ca4afSHartmut Brandt 1033f06ca4afSHartmut Brandt case SNMP_SYNTAX_IPADDRESS: 1034f06ca4afSHartmut Brandt snmp_printf("IPADDRESS %u.%u.%u.%u", b->v.ipaddress[0], 1035f06ca4afSHartmut Brandt b->v.ipaddress[1], b->v.ipaddress[2], b->v.ipaddress[3]); 1036f06ca4afSHartmut Brandt break; 1037f06ca4afSHartmut Brandt 1038f06ca4afSHartmut Brandt case SNMP_SYNTAX_COUNTER: 1039f06ca4afSHartmut Brandt snmp_printf("COUNTER %u", b->v.uint32); 1040f06ca4afSHartmut Brandt break; 1041f06ca4afSHartmut Brandt 1042f06ca4afSHartmut Brandt case SNMP_SYNTAX_GAUGE: 1043f06ca4afSHartmut Brandt snmp_printf("GAUGE %u", b->v.uint32); 1044f06ca4afSHartmut Brandt break; 1045f06ca4afSHartmut Brandt 1046f06ca4afSHartmut Brandt case SNMP_SYNTAX_TIMETICKS: 1047f06ca4afSHartmut Brandt snmp_printf("TIMETICKS %u", b->v.uint32); 1048f06ca4afSHartmut Brandt break; 1049f06ca4afSHartmut Brandt 1050f06ca4afSHartmut Brandt case SNMP_SYNTAX_COUNTER64: 1051f06ca4afSHartmut Brandt snmp_printf("COUNTER64 %lld", b->v.counter64); 1052f06ca4afSHartmut Brandt break; 1053f06ca4afSHartmut Brandt 1054f06ca4afSHartmut Brandt case SNMP_SYNTAX_NOSUCHOBJECT: 1055f06ca4afSHartmut Brandt snmp_printf("NoSuchObject"); 1056f06ca4afSHartmut Brandt break; 1057f06ca4afSHartmut Brandt 1058f06ca4afSHartmut Brandt case SNMP_SYNTAX_NOSUCHINSTANCE: 1059f06ca4afSHartmut Brandt snmp_printf("NoSuchInstance"); 1060f06ca4afSHartmut Brandt break; 1061f06ca4afSHartmut Brandt 1062f06ca4afSHartmut Brandt case SNMP_SYNTAX_ENDOFMIBVIEW: 1063f06ca4afSHartmut Brandt snmp_printf("EndOfMibView"); 1064f06ca4afSHartmut Brandt break; 1065f06ca4afSHartmut Brandt 1066f06ca4afSHartmut Brandt default: 1067f06ca4afSHartmut Brandt snmp_printf("UNKNOWN SYNTAX %u", b->syntax); 1068f06ca4afSHartmut Brandt break; 1069f06ca4afSHartmut Brandt } 1070f06ca4afSHartmut Brandt } 1071f06ca4afSHartmut Brandt 1072f06ca4afSHartmut Brandt static __inline void 1073f06ca4afSHartmut Brandt dump_bindings(const struct snmp_pdu *pdu) 1074f06ca4afSHartmut Brandt { 1075f06ca4afSHartmut Brandt u_int i; 1076f06ca4afSHartmut Brandt 1077f06ca4afSHartmut Brandt for (i = 0; i < pdu->nbindings; i++) { 1078f06ca4afSHartmut Brandt snmp_printf(" [%u]: ", i); 1079f06ca4afSHartmut Brandt dump_binding(&pdu->bindings[i]); 1080f06ca4afSHartmut Brandt snmp_printf("\n"); 1081f06ca4afSHartmut Brandt } 1082f06ca4afSHartmut Brandt } 1083f06ca4afSHartmut Brandt 1084f06ca4afSHartmut Brandt static __inline void 1085f06ca4afSHartmut Brandt dump_notrap(const struct snmp_pdu *pdu) 1086f06ca4afSHartmut Brandt { 1087f06ca4afSHartmut Brandt snmp_printf(" request_id=%d", pdu->request_id); 1088f06ca4afSHartmut Brandt snmp_printf(" error_status=%d", pdu->error_status); 1089f06ca4afSHartmut Brandt snmp_printf(" error_index=%d\n", pdu->error_index); 1090f06ca4afSHartmut Brandt dump_bindings(pdu); 1091f06ca4afSHartmut Brandt } 1092f06ca4afSHartmut Brandt 1093f06ca4afSHartmut Brandt void 1094f06ca4afSHartmut Brandt snmp_pdu_dump(const struct snmp_pdu *pdu) 1095f06ca4afSHartmut Brandt { 1096f06ca4afSHartmut Brandt char buf[ASN_OIDSTRLEN]; 1097f06ca4afSHartmut Brandt const char *vers; 1098f06ca4afSHartmut Brandt static const char *types[] = { 1099f06ca4afSHartmut Brandt [SNMP_PDU_GET] = "GET", 1100f06ca4afSHartmut Brandt [SNMP_PDU_GETNEXT] = "GETNEXT", 1101f06ca4afSHartmut Brandt [SNMP_PDU_RESPONSE] = "RESPONSE", 1102f06ca4afSHartmut Brandt [SNMP_PDU_SET] = "SET", 1103f06ca4afSHartmut Brandt [SNMP_PDU_TRAP] = "TRAPv1", 1104f06ca4afSHartmut Brandt [SNMP_PDU_GETBULK] = "GETBULK", 1105f06ca4afSHartmut Brandt [SNMP_PDU_INFORM] = "INFORM", 1106f06ca4afSHartmut Brandt [SNMP_PDU_TRAP2] = "TRAPv2", 1107f06ca4afSHartmut Brandt [SNMP_PDU_REPORT] = "REPORT", 1108f06ca4afSHartmut Brandt }; 1109f06ca4afSHartmut Brandt 1110f06ca4afSHartmut Brandt if (pdu->version == SNMP_V1) 1111f06ca4afSHartmut Brandt vers = "SNMPv1"; 1112f06ca4afSHartmut Brandt else if (pdu->version == SNMP_V2c) 1113f06ca4afSHartmut Brandt vers = "SNMPv2c"; 1114135f7de5SShteryana Shopova else if (pdu->version == SNMP_V3) 1115135f7de5SShteryana Shopova vers = "SNMPv3"; 1116f06ca4afSHartmut Brandt else 1117f06ca4afSHartmut Brandt vers = "v?"; 1118f06ca4afSHartmut Brandt 1119f06ca4afSHartmut Brandt switch (pdu->type) { 1120f06ca4afSHartmut Brandt case SNMP_PDU_TRAP: 1121f06ca4afSHartmut Brandt snmp_printf("%s %s '%s'", types[pdu->type], vers, pdu->community); 1122f06ca4afSHartmut Brandt snmp_printf(" enterprise=%s", asn_oid2str_r(&pdu->enterprise, buf)); 1123f06ca4afSHartmut Brandt snmp_printf(" agent_addr=%u.%u.%u.%u", pdu->agent_addr[0], 1124f06ca4afSHartmut Brandt pdu->agent_addr[1], pdu->agent_addr[2], pdu->agent_addr[3]); 1125f06ca4afSHartmut Brandt snmp_printf(" generic_trap=%d", pdu->generic_trap); 1126f06ca4afSHartmut Brandt snmp_printf(" specific_trap=%d", pdu->specific_trap); 1127f06ca4afSHartmut Brandt snmp_printf(" time-stamp=%u\n", pdu->time_stamp); 1128f06ca4afSHartmut Brandt dump_bindings(pdu); 1129f06ca4afSHartmut Brandt break; 1130f06ca4afSHartmut Brandt 1131f06ca4afSHartmut Brandt case SNMP_PDU_GET: 1132f06ca4afSHartmut Brandt case SNMP_PDU_GETNEXT: 1133f06ca4afSHartmut Brandt case SNMP_PDU_RESPONSE: 1134f06ca4afSHartmut Brandt case SNMP_PDU_SET: 1135f06ca4afSHartmut Brandt case SNMP_PDU_GETBULK: 1136f06ca4afSHartmut Brandt case SNMP_PDU_INFORM: 1137f06ca4afSHartmut Brandt case SNMP_PDU_TRAP2: 1138f06ca4afSHartmut Brandt case SNMP_PDU_REPORT: 1139f06ca4afSHartmut Brandt snmp_printf("%s %s '%s'", types[pdu->type], vers, pdu->community); 1140f06ca4afSHartmut Brandt dump_notrap(pdu); 1141f06ca4afSHartmut Brandt break; 1142f06ca4afSHartmut Brandt 1143f06ca4afSHartmut Brandt default: 1144f06ca4afSHartmut Brandt snmp_printf("bad pdu type %u\n", pdu->type); 1145f06ca4afSHartmut Brandt break; 1146f06ca4afSHartmut Brandt } 1147f06ca4afSHartmut Brandt } 1148f06ca4afSHartmut Brandt 1149f06ca4afSHartmut Brandt void 1150f06ca4afSHartmut Brandt snmp_value_free(struct snmp_value *value) 1151f06ca4afSHartmut Brandt { 1152f06ca4afSHartmut Brandt if (value->syntax == SNMP_SYNTAX_OCTETSTRING) 1153f06ca4afSHartmut Brandt free(value->v.octetstring.octets); 1154f06ca4afSHartmut Brandt value->syntax = SNMP_SYNTAX_NULL; 1155f06ca4afSHartmut Brandt } 1156f06ca4afSHartmut Brandt 1157f06ca4afSHartmut Brandt int 1158f06ca4afSHartmut Brandt snmp_value_copy(struct snmp_value *to, const struct snmp_value *from) 1159f06ca4afSHartmut Brandt { 1160f06ca4afSHartmut Brandt to->var = from->var; 1161f06ca4afSHartmut Brandt to->syntax = from->syntax; 1162f06ca4afSHartmut Brandt 1163f06ca4afSHartmut Brandt if (from->syntax == SNMP_SYNTAX_OCTETSTRING) { 1164f06ca4afSHartmut Brandt if ((to->v.octetstring.len = from->v.octetstring.len) == 0) 1165f06ca4afSHartmut Brandt to->v.octetstring.octets = NULL; 1166f06ca4afSHartmut Brandt else { 1167f06ca4afSHartmut Brandt to->v.octetstring.octets = malloc(to->v.octetstring.len); 1168f06ca4afSHartmut Brandt if (to->v.octetstring.octets == NULL) 1169f06ca4afSHartmut Brandt return (-1); 1170f06ca4afSHartmut Brandt (void)memcpy(to->v.octetstring.octets, 1171f06ca4afSHartmut Brandt from->v.octetstring.octets, to->v.octetstring.len); 1172f06ca4afSHartmut Brandt } 1173f06ca4afSHartmut Brandt } else 1174f06ca4afSHartmut Brandt to->v = from->v; 1175f06ca4afSHartmut Brandt return (0); 1176f06ca4afSHartmut Brandt } 1177f06ca4afSHartmut Brandt 1178f06ca4afSHartmut Brandt void 1179135f7de5SShteryana Shopova snmp_pdu_init_secparams(struct snmp_pdu *pdu, struct snmp_engine *eng, 1180135f7de5SShteryana Shopova struct snmp_user *user) 1181135f7de5SShteryana Shopova { 1182135f7de5SShteryana Shopova int32_t rval; 1183135f7de5SShteryana Shopova 1184135f7de5SShteryana Shopova memcpy(&pdu->engine, eng, sizeof(pdu->engine)); 1185135f7de5SShteryana Shopova memcpy(&pdu->user, user, sizeof(pdu->user)); 1186135f7de5SShteryana Shopova 1187135f7de5SShteryana Shopova if (user->auth_proto != SNMP_AUTH_NOAUTH) 1188135f7de5SShteryana Shopova pdu->flags |= SNMP_MSG_AUTH_FLAG; 1189135f7de5SShteryana Shopova 1190135f7de5SShteryana Shopova switch (user->priv_proto) { 1191135f7de5SShteryana Shopova case SNMP_PRIV_DES: 1192135f7de5SShteryana Shopova memcpy(pdu->msg_salt, &eng->engine_boots, 1193135f7de5SShteryana Shopova sizeof(eng->engine_boots)); 1194135f7de5SShteryana Shopova rval = random(); 1195135f7de5SShteryana Shopova memcpy(pdu->msg_salt + sizeof(eng->engine_boots), &rval, 1196135f7de5SShteryana Shopova sizeof(int32_t)); 1197135f7de5SShteryana Shopova pdu->flags |= SNMP_MSG_PRIV_FLAG; 1198135f7de5SShteryana Shopova break; 1199135f7de5SShteryana Shopova case SNMP_PRIV_AES: 1200135f7de5SShteryana Shopova rval = random(); 1201135f7de5SShteryana Shopova memcpy(pdu->msg_salt, &rval, sizeof(int32_t)); 1202135f7de5SShteryana Shopova rval = random(); 1203135f7de5SShteryana Shopova memcpy(pdu->msg_salt + sizeof(int32_t), &rval, sizeof(int32_t)); 1204135f7de5SShteryana Shopova pdu->flags |= SNMP_MSG_PRIV_FLAG; 1205135f7de5SShteryana Shopova break; 1206135f7de5SShteryana Shopova default: 1207135f7de5SShteryana Shopova break; 1208135f7de5SShteryana Shopova } 1209135f7de5SShteryana Shopova } 1210135f7de5SShteryana Shopova 1211135f7de5SShteryana Shopova void 1212f06ca4afSHartmut Brandt snmp_pdu_free(struct snmp_pdu *pdu) 1213f06ca4afSHartmut Brandt { 1214f06ca4afSHartmut Brandt u_int i; 1215f06ca4afSHartmut Brandt 1216f06ca4afSHartmut Brandt for (i = 0; i < pdu->nbindings; i++) 1217f06ca4afSHartmut Brandt snmp_value_free(&pdu->bindings[i]); 1218f06ca4afSHartmut Brandt } 1219f06ca4afSHartmut Brandt 1220f06ca4afSHartmut Brandt /* 1221f06ca4afSHartmut Brandt * Parse an ASCII SNMP value into the binary form 1222f06ca4afSHartmut Brandt */ 1223f06ca4afSHartmut Brandt int 1224f06ca4afSHartmut Brandt snmp_value_parse(const char *str, enum snmp_syntax syntax, union snmp_values *v) 1225f06ca4afSHartmut Brandt { 1226f06ca4afSHartmut Brandt char *end; 1227f06ca4afSHartmut Brandt 1228f06ca4afSHartmut Brandt switch (syntax) { 1229f06ca4afSHartmut Brandt 1230f06ca4afSHartmut Brandt case SNMP_SYNTAX_NULL: 1231f06ca4afSHartmut Brandt case SNMP_SYNTAX_NOSUCHOBJECT: 1232f06ca4afSHartmut Brandt case SNMP_SYNTAX_NOSUCHINSTANCE: 1233f06ca4afSHartmut Brandt case SNMP_SYNTAX_ENDOFMIBVIEW: 1234f06ca4afSHartmut Brandt if (*str != '\0') 1235f06ca4afSHartmut Brandt return (-1); 1236f06ca4afSHartmut Brandt return (0); 1237f06ca4afSHartmut Brandt 1238f06ca4afSHartmut Brandt case SNMP_SYNTAX_INTEGER: 1239f06ca4afSHartmut Brandt v->integer = strtoll(str, &end, 0); 1240f06ca4afSHartmut Brandt if (*end != '\0') 1241f06ca4afSHartmut Brandt return (-1); 1242f06ca4afSHartmut Brandt return (0); 1243f06ca4afSHartmut Brandt 1244f06ca4afSHartmut Brandt case SNMP_SYNTAX_OCTETSTRING: 1245f06ca4afSHartmut Brandt { 1246f06ca4afSHartmut Brandt u_long len; /* actual length of string */ 1247f06ca4afSHartmut Brandt u_long alloc; /* allocate length of string */ 1248f06ca4afSHartmut Brandt u_char *octs; /* actual octets */ 1249f06ca4afSHartmut Brandt u_long oct; /* actual octet */ 1250f06ca4afSHartmut Brandt u_char *nocts; /* to avoid memory leak */ 1251f06ca4afSHartmut Brandt u_char c; /* actual character */ 1252f06ca4afSHartmut Brandt 1253f06ca4afSHartmut Brandt # define STUFFC(C) \ 1254f06ca4afSHartmut Brandt if (alloc == len) { \ 1255f06ca4afSHartmut Brandt alloc += 100; \ 1256f06ca4afSHartmut Brandt if ((nocts = realloc(octs, alloc)) == NULL) { \ 1257f06ca4afSHartmut Brandt free(octs); \ 1258f06ca4afSHartmut Brandt return (-1); \ 1259f06ca4afSHartmut Brandt } \ 1260f06ca4afSHartmut Brandt octs = nocts; \ 1261f06ca4afSHartmut Brandt } \ 1262f06ca4afSHartmut Brandt octs[len++] = (C); 1263f06ca4afSHartmut Brandt 1264f06ca4afSHartmut Brandt len = alloc = 0; 1265f06ca4afSHartmut Brandt octs = NULL; 1266f06ca4afSHartmut Brandt 1267f06ca4afSHartmut Brandt if (*str == '"') { 1268f06ca4afSHartmut Brandt str++; 1269f06ca4afSHartmut Brandt while((c = *str++) != '\0') { 1270f06ca4afSHartmut Brandt if (c == '"') { 1271f06ca4afSHartmut Brandt if (*str != '\0') { 1272f06ca4afSHartmut Brandt free(octs); 1273f06ca4afSHartmut Brandt return (-1); 1274f06ca4afSHartmut Brandt } 1275f06ca4afSHartmut Brandt break; 1276f06ca4afSHartmut Brandt } 1277f06ca4afSHartmut Brandt if (c == '\\') { 1278f06ca4afSHartmut Brandt switch (c = *str++) { 1279f06ca4afSHartmut Brandt 1280f06ca4afSHartmut Brandt case '\\': 1281f06ca4afSHartmut Brandt break; 1282f06ca4afSHartmut Brandt case 'a': 1283f06ca4afSHartmut Brandt c = '\a'; 1284f06ca4afSHartmut Brandt break; 1285f06ca4afSHartmut Brandt case 'b': 1286f06ca4afSHartmut Brandt c = '\b'; 1287f06ca4afSHartmut Brandt break; 1288f06ca4afSHartmut Brandt case 'f': 1289f06ca4afSHartmut Brandt c = '\f'; 1290f06ca4afSHartmut Brandt break; 1291f06ca4afSHartmut Brandt case 'n': 1292f06ca4afSHartmut Brandt c = '\n'; 1293f06ca4afSHartmut Brandt break; 1294f06ca4afSHartmut Brandt case 'r': 1295f06ca4afSHartmut Brandt c = '\r'; 1296f06ca4afSHartmut Brandt break; 1297f06ca4afSHartmut Brandt case 't': 1298f06ca4afSHartmut Brandt c = '\t'; 1299f06ca4afSHartmut Brandt break; 1300f06ca4afSHartmut Brandt case 'v': 1301f06ca4afSHartmut Brandt c = '\v'; 1302f06ca4afSHartmut Brandt break; 1303f06ca4afSHartmut Brandt case 'x': 1304f06ca4afSHartmut Brandt c = 0; 1305f06ca4afSHartmut Brandt if (!isxdigit(*str)) 1306f06ca4afSHartmut Brandt break; 1307f06ca4afSHartmut Brandt if (isdigit(*str)) 1308f06ca4afSHartmut Brandt c = *str++ - '0'; 1309f06ca4afSHartmut Brandt else if (isupper(*str)) 1310f06ca4afSHartmut Brandt c = *str++ - 'A' + 10; 1311f06ca4afSHartmut Brandt else 1312f06ca4afSHartmut Brandt c = *str++ - 'a' + 10; 1313f06ca4afSHartmut Brandt if (!isxdigit(*str)) 1314f06ca4afSHartmut Brandt break; 1315f06ca4afSHartmut Brandt if (isdigit(*str)) 1316f06ca4afSHartmut Brandt c += *str++ - '0'; 1317f06ca4afSHartmut Brandt else if (isupper(*str)) 1318f06ca4afSHartmut Brandt c += *str++ - 'A' + 10; 1319f06ca4afSHartmut Brandt else 1320f06ca4afSHartmut Brandt c += *str++ - 'a' + 10; 1321f06ca4afSHartmut Brandt break; 1322f06ca4afSHartmut Brandt case '0': case '1': case '2': 1323f06ca4afSHartmut Brandt case '3': case '4': case '5': 1324f06ca4afSHartmut Brandt case '6': case '7': 1325f06ca4afSHartmut Brandt c = *str++ - '0'; 1326f06ca4afSHartmut Brandt if (*str < '0' || *str > '7') 1327f06ca4afSHartmut Brandt break; 1328f06ca4afSHartmut Brandt c = *str++ - '0'; 1329f06ca4afSHartmut Brandt if (*str < '0' || *str > '7') 1330f06ca4afSHartmut Brandt break; 1331f06ca4afSHartmut Brandt c = *str++ - '0'; 1332f06ca4afSHartmut Brandt break; 1333f06ca4afSHartmut Brandt default: 1334f06ca4afSHartmut Brandt break; 1335f06ca4afSHartmut Brandt } 1336f06ca4afSHartmut Brandt } 1337f06ca4afSHartmut Brandt STUFFC(c); 1338f06ca4afSHartmut Brandt } 1339f06ca4afSHartmut Brandt } else { 1340f06ca4afSHartmut Brandt while (*str != '\0') { 1341f06ca4afSHartmut Brandt oct = strtoul(str, &end, 16); 1342f06ca4afSHartmut Brandt str = end; 1343f06ca4afSHartmut Brandt if (oct > 0xff) { 1344f06ca4afSHartmut Brandt free(octs); 1345f06ca4afSHartmut Brandt return (-1); 1346f06ca4afSHartmut Brandt } 1347f06ca4afSHartmut Brandt STUFFC(oct); 1348f06ca4afSHartmut Brandt if (*str == ':') 1349f06ca4afSHartmut Brandt str++; 1350f06ca4afSHartmut Brandt else if(*str != '\0') { 1351f06ca4afSHartmut Brandt free(octs); 1352f06ca4afSHartmut Brandt return (-1); 1353f06ca4afSHartmut Brandt } 1354f06ca4afSHartmut Brandt } 1355f06ca4afSHartmut Brandt } 1356f06ca4afSHartmut Brandt v->octetstring.octets = octs; 1357f06ca4afSHartmut Brandt v->octetstring.len = len; 1358f06ca4afSHartmut Brandt return (0); 1359f06ca4afSHartmut Brandt # undef STUFFC 1360f06ca4afSHartmut Brandt } 1361f06ca4afSHartmut Brandt 1362f06ca4afSHartmut Brandt case SNMP_SYNTAX_OID: 1363f06ca4afSHartmut Brandt { 1364f06ca4afSHartmut Brandt u_long subid; 1365f06ca4afSHartmut Brandt 1366f06ca4afSHartmut Brandt v->oid.len = 0; 1367f06ca4afSHartmut Brandt 1368f06ca4afSHartmut Brandt for (;;) { 1369f06ca4afSHartmut Brandt if (v->oid.len == ASN_MAXOIDLEN) 1370f06ca4afSHartmut Brandt return (-1); 1371f06ca4afSHartmut Brandt subid = strtoul(str, &end, 10); 1372f06ca4afSHartmut Brandt str = end; 1373f06ca4afSHartmut Brandt if (subid > ASN_MAXID) 1374f06ca4afSHartmut Brandt return (-1); 1375f06ca4afSHartmut Brandt v->oid.subs[v->oid.len++] = (asn_subid_t)subid; 1376f06ca4afSHartmut Brandt if (*str == '\0') 1377f06ca4afSHartmut Brandt break; 1378f06ca4afSHartmut Brandt if (*str != '.') 1379f06ca4afSHartmut Brandt return (-1); 1380f06ca4afSHartmut Brandt str++; 1381f06ca4afSHartmut Brandt } 1382f06ca4afSHartmut Brandt return (0); 1383f06ca4afSHartmut Brandt } 1384f06ca4afSHartmut Brandt 1385f06ca4afSHartmut Brandt case SNMP_SYNTAX_IPADDRESS: 1386f06ca4afSHartmut Brandt { 1387f06ca4afSHartmut Brandt struct hostent *he; 1388f06ca4afSHartmut Brandt u_long ip[4]; 1389f06ca4afSHartmut Brandt int n; 1390f06ca4afSHartmut Brandt 1391f06ca4afSHartmut Brandt if (sscanf(str, "%lu.%lu.%lu.%lu%n", &ip[0], &ip[1], &ip[2], 1392f06ca4afSHartmut Brandt &ip[3], &n) == 4 && (size_t)n == strlen(str) && 1393f06ca4afSHartmut Brandt ip[0] <= 0xff && ip[1] <= 0xff && 1394f06ca4afSHartmut Brandt ip[2] <= 0xff && ip[3] <= 0xff) { 1395f06ca4afSHartmut Brandt v->ipaddress[0] = (u_char)ip[0]; 1396f06ca4afSHartmut Brandt v->ipaddress[1] = (u_char)ip[1]; 1397f06ca4afSHartmut Brandt v->ipaddress[2] = (u_char)ip[2]; 1398f06ca4afSHartmut Brandt v->ipaddress[3] = (u_char)ip[3]; 1399f06ca4afSHartmut Brandt return (0); 1400f06ca4afSHartmut Brandt } 1401f06ca4afSHartmut Brandt 1402f06ca4afSHartmut Brandt if ((he = gethostbyname(str)) == NULL) 1403f06ca4afSHartmut Brandt return (-1); 1404f06ca4afSHartmut Brandt if (he->h_addrtype != AF_INET) 1405f06ca4afSHartmut Brandt return (-1); 1406f06ca4afSHartmut Brandt 1407f06ca4afSHartmut Brandt v->ipaddress[0] = he->h_addr[0]; 1408f06ca4afSHartmut Brandt v->ipaddress[1] = he->h_addr[1]; 1409f06ca4afSHartmut Brandt v->ipaddress[2] = he->h_addr[2]; 1410f06ca4afSHartmut Brandt v->ipaddress[3] = he->h_addr[3]; 1411f06ca4afSHartmut Brandt return (0); 1412f06ca4afSHartmut Brandt } 1413f06ca4afSHartmut Brandt 1414f06ca4afSHartmut Brandt case SNMP_SYNTAX_COUNTER: 1415f06ca4afSHartmut Brandt case SNMP_SYNTAX_GAUGE: 1416f06ca4afSHartmut Brandt case SNMP_SYNTAX_TIMETICKS: 1417f06ca4afSHartmut Brandt { 1418896052c1SHartmut Brandt uint64_t sub; 1419f06ca4afSHartmut Brandt 1420f06ca4afSHartmut Brandt sub = strtoull(str, &end, 0); 1421f06ca4afSHartmut Brandt if (*end != '\0' || sub > 0xffffffff) 1422f06ca4afSHartmut Brandt return (-1); 1423896052c1SHartmut Brandt v->uint32 = (uint32_t)sub; 1424f06ca4afSHartmut Brandt return (0); 1425f06ca4afSHartmut Brandt } 1426f06ca4afSHartmut Brandt 1427f06ca4afSHartmut Brandt case SNMP_SYNTAX_COUNTER64: 1428f06ca4afSHartmut Brandt v->counter64 = strtoull(str, &end, 0); 1429f06ca4afSHartmut Brandt if (*end != '\0') 1430f06ca4afSHartmut Brandt return (-1); 1431f06ca4afSHartmut Brandt return (0); 1432f06ca4afSHartmut Brandt } 1433f06ca4afSHartmut Brandt abort(); 1434f06ca4afSHartmut Brandt } 1435f06ca4afSHartmut Brandt 1436f06ca4afSHartmut Brandt static void 1437f06ca4afSHartmut Brandt snmp_error_func(const char *fmt, ...) 1438f06ca4afSHartmut Brandt { 1439f06ca4afSHartmut Brandt va_list ap; 1440f06ca4afSHartmut Brandt 1441f06ca4afSHartmut Brandt va_start(ap, fmt); 1442f06ca4afSHartmut Brandt fprintf(stderr, "SNMP: "); 1443f06ca4afSHartmut Brandt vfprintf(stderr, fmt, ap); 1444f06ca4afSHartmut Brandt fprintf(stderr, "\n"); 1445f06ca4afSHartmut Brandt va_end(ap); 1446f06ca4afSHartmut Brandt } 1447f06ca4afSHartmut Brandt 1448f06ca4afSHartmut Brandt static void 1449f06ca4afSHartmut Brandt snmp_printf_func(const char *fmt, ...) 1450f06ca4afSHartmut Brandt { 1451f06ca4afSHartmut Brandt va_list ap; 1452f06ca4afSHartmut Brandt 1453f06ca4afSHartmut Brandt va_start(ap, fmt); 1454f06ca4afSHartmut Brandt vfprintf(stderr, fmt, ap); 1455f06ca4afSHartmut Brandt va_end(ap); 1456f06ca4afSHartmut Brandt } 1457