1122394Sharti/* 2122394Sharti * Copyright (c) 2001-2003 3122394Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4122394Sharti * All rights reserved. 5122394Sharti * 6122394Sharti * Author: Harti Brandt <harti@freebsd.org> 7310903Sngie * 8216294Ssyrinx * Copyright (c) 2010 The FreeBSD Foundation 9216294Ssyrinx * All rights reserved. 10216294Ssyrinx * 11216294Ssyrinx * Portions of this software were developed by Shteryana Sotirova Shopova 12216294Ssyrinx * under sponsorship from the FreeBSD Foundation. 13216294Ssyrinx * 14133211Sharti * Redistribution and use in source and binary forms, with or without 15133211Sharti * modification, are permitted provided that the following conditions 16133211Sharti * are met: 17133211Sharti * 1. Redistributions of source code must retain the above copyright 18133211Sharti * notice, this list of conditions and the following disclaimer. 19122394Sharti * 2. Redistributions in binary form must reproduce the above copyright 20122394Sharti * notice, this list of conditions and the following disclaimer in the 21122394Sharti * documentation and/or other materials provided with the distribution. 22310903Sngie * 23133211Sharti * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24133211Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25133211Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26133211Sharti * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 27133211Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28133211Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29133211Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30133211Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31133211Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32133211Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33133211Sharti * SUCH DAMAGE. 34122394Sharti * 35150920Sharti * $Begemot: bsnmp/lib/snmp.c,v 1.40 2005/10/04 14:32:42 brandt_h Exp $ 36122394Sharti * 37122394Sharti * SNMP 38122394Sharti */ 39122394Sharti#include <sys/types.h> 40122394Sharti#include <sys/socket.h> 41310673Sngie#include <ctype.h> 42310673Sngie#include <errno.h> 43310673Sngie#include <netdb.h> 44122394Sharti#include <stdio.h> 45122394Sharti#include <stdlib.h> 46122394Sharti#include <stddef.h> 47122394Sharti#include <stdarg.h> 48310673Sngie#include <string.h> 49150920Sharti#ifdef HAVE_STDINT_H 50133211Sharti#include <stdint.h> 51150920Sharti#elif defined(HAVE_INTTYPES_H) 52150920Sharti#include <inttypes.h> 53150920Sharti#endif 54311603Sngie#include <netinet/in.h> 55311603Sngie#include <arpa/inet.h> 56122394Sharti 57122394Sharti#include "asn1.h" 58122394Sharti#include "snmp.h" 59122394Sharti#include "snmppriv.h" 60122394Sharti 61122394Shartistatic void snmp_error_func(const char *, ...); 62122394Shartistatic void snmp_printf_func(const char *, ...); 63122394Sharti 64122394Shartivoid (*snmp_error)(const char *, ...) = snmp_error_func; 65122394Shartivoid (*snmp_printf)(const char *, ...) = snmp_printf_func; 66122394Sharti 67122394Sharti/* 68122394Sharti * Get the next variable binding from the list. 69122394Sharti * ASN errors on the sequence or the OID are always fatal. 70122394Sharti */ 71122394Shartistatic enum asn_err 72122394Shartiget_var_binding(struct asn_buf *b, struct snmp_value *binding) 73122394Sharti{ 74122394Sharti u_char type; 75122394Sharti asn_len_t len, trailer; 76122394Sharti enum asn_err err; 77122394Sharti 78122394Sharti if (asn_get_sequence(b, &len) != ASN_ERR_OK) { 79122394Sharti snmp_error("cannot parse varbind header"); 80122394Sharti return (ASN_ERR_FAILED); 81122394Sharti } 82122394Sharti 83122394Sharti /* temporary truncate the length so that the parser does not 84122394Sharti * eat up bytes behind the sequence in the case the encoding is 85122394Sharti * wrong of inner elements. */ 86122394Sharti trailer = b->asn_len - len; 87122394Sharti b->asn_len = len; 88122394Sharti 89122394Sharti if (asn_get_objid(b, &binding->var) != ASN_ERR_OK) { 90122394Sharti snmp_error("cannot parse binding objid"); 91122394Sharti return (ASN_ERR_FAILED); 92122394Sharti } 93122394Sharti if (asn_get_header(b, &type, &len) != ASN_ERR_OK) { 94122394Sharti snmp_error("cannot parse binding value header"); 95122394Sharti return (ASN_ERR_FAILED); 96122394Sharti } 97122394Sharti 98122394Sharti switch (type) { 99122394Sharti 100122394Sharti case ASN_TYPE_NULL: 101122394Sharti binding->syntax = SNMP_SYNTAX_NULL; 102122394Sharti err = asn_get_null_raw(b, len); 103122394Sharti break; 104122394Sharti 105122394Sharti case ASN_TYPE_INTEGER: 106122394Sharti binding->syntax = SNMP_SYNTAX_INTEGER; 107122394Sharti err = asn_get_integer_raw(b, len, &binding->v.integer); 108122394Sharti break; 109122394Sharti 110122394Sharti case ASN_TYPE_OCTETSTRING: 111122394Sharti binding->syntax = SNMP_SYNTAX_OCTETSTRING; 112122394Sharti binding->v.octetstring.octets = malloc(len); 113122394Sharti if (binding->v.octetstring.octets == NULL) { 114122394Sharti snmp_error("%s", strerror(errno)); 115122394Sharti return (ASN_ERR_FAILED); 116122394Sharti } 117122394Sharti binding->v.octetstring.len = len; 118122394Sharti err = asn_get_octetstring_raw(b, len, 119122394Sharti binding->v.octetstring.octets, 120122394Sharti &binding->v.octetstring.len); 121122394Sharti if (ASN_ERR_STOPPED(err)) { 122122394Sharti free(binding->v.octetstring.octets); 123122394Sharti binding->v.octetstring.octets = NULL; 124122394Sharti } 125122394Sharti break; 126122394Sharti 127122394Sharti case ASN_TYPE_OBJID: 128122394Sharti binding->syntax = SNMP_SYNTAX_OID; 129122394Sharti err = asn_get_objid_raw(b, len, &binding->v.oid); 130122394Sharti break; 131122394Sharti 132122394Sharti case ASN_CLASS_APPLICATION|ASN_APP_IPADDRESS: 133122394Sharti binding->syntax = SNMP_SYNTAX_IPADDRESS; 134122394Sharti err = asn_get_ipaddress_raw(b, len, binding->v.ipaddress); 135122394Sharti break; 136122394Sharti 137122394Sharti case ASN_CLASS_APPLICATION|ASN_APP_TIMETICKS: 138122394Sharti binding->syntax = SNMP_SYNTAX_TIMETICKS; 139122394Sharti err = asn_get_uint32_raw(b, len, &binding->v.uint32); 140122394Sharti break; 141122394Sharti 142122394Sharti case ASN_CLASS_APPLICATION|ASN_APP_COUNTER: 143122394Sharti binding->syntax = SNMP_SYNTAX_COUNTER; 144122394Sharti err = asn_get_uint32_raw(b, len, &binding->v.uint32); 145122394Sharti break; 146122394Sharti 147122394Sharti case ASN_CLASS_APPLICATION|ASN_APP_GAUGE: 148122394Sharti binding->syntax = SNMP_SYNTAX_GAUGE; 149122394Sharti err = asn_get_uint32_raw(b, len, &binding->v.uint32); 150122394Sharti break; 151122394Sharti 152122394Sharti case ASN_CLASS_APPLICATION|ASN_APP_COUNTER64: 153122394Sharti binding->syntax = SNMP_SYNTAX_COUNTER64; 154122394Sharti err = asn_get_counter64_raw(b, len, &binding->v.counter64); 155122394Sharti break; 156122394Sharti 157122394Sharti case ASN_CLASS_CONTEXT | ASN_EXCEPT_NOSUCHOBJECT: 158122394Sharti binding->syntax = SNMP_SYNTAX_NOSUCHOBJECT; 159122394Sharti err = asn_get_null_raw(b, len); 160122394Sharti break; 161122394Sharti 162122394Sharti case ASN_CLASS_CONTEXT | ASN_EXCEPT_NOSUCHINSTANCE: 163122394Sharti binding->syntax = SNMP_SYNTAX_NOSUCHINSTANCE; 164122394Sharti err = asn_get_null_raw(b, len); 165122394Sharti break; 166122394Sharti 167122394Sharti case ASN_CLASS_CONTEXT | ASN_EXCEPT_ENDOFMIBVIEW: 168122394Sharti binding->syntax = SNMP_SYNTAX_ENDOFMIBVIEW; 169122394Sharti err = asn_get_null_raw(b, len); 170122394Sharti break; 171122394Sharti 172122394Sharti default: 173122394Sharti if ((err = asn_skip(b, len)) == ASN_ERR_OK) 174122394Sharti err = ASN_ERR_TAG; 175122394Sharti snmp_error("bad binding value type 0x%x", type); 176122394Sharti break; 177122394Sharti } 178122394Sharti 179122394Sharti if (ASN_ERR_STOPPED(err)) { 180122394Sharti snmp_error("cannot parse binding value"); 181122394Sharti return (err); 182122394Sharti } 183122394Sharti 184122394Sharti if (b->asn_len != 0) 185122394Sharti snmp_error("ignoring junk at end of binding"); 186122394Sharti 187122394Sharti b->asn_len = trailer; 188122394Sharti 189122394Sharti return (err); 190122394Sharti} 191122394Sharti 192122394Sharti/* 193122394Sharti * Parse the different PDUs contents. Any ASN error in the outer components 194122394Sharti * are fatal. Only errors in variable values may be tolerated. If all 195122394Sharti * components can be parsed it returns either ASN_ERR_OK or the first 196122394Sharti * error that was found. 197122394Sharti */ 198122394Shartienum asn_err 199122394Shartisnmp_parse_pdus_hdr(struct asn_buf *b, struct snmp_pdu *pdu, asn_len_t *lenp) 200122394Sharti{ 201122394Sharti if (pdu->type == SNMP_PDU_TRAP) { 202122394Sharti if (asn_get_objid(b, &pdu->enterprise) != ASN_ERR_OK) { 203122394Sharti snmp_error("cannot parse trap enterprise"); 204122394Sharti return (ASN_ERR_FAILED); 205122394Sharti } 206122394Sharti if (asn_get_ipaddress(b, pdu->agent_addr) != ASN_ERR_OK) { 207122394Sharti snmp_error("cannot parse trap agent address"); 208122394Sharti return (ASN_ERR_FAILED); 209122394Sharti } 210122394Sharti if (asn_get_integer(b, &pdu->generic_trap) != ASN_ERR_OK) { 211122394Sharti snmp_error("cannot parse 'generic-trap'"); 212122394Sharti return (ASN_ERR_FAILED); 213122394Sharti } 214122394Sharti if (asn_get_integer(b, &pdu->specific_trap) != ASN_ERR_OK) { 215122394Sharti snmp_error("cannot parse 'specific-trap'"); 216122394Sharti return (ASN_ERR_FAILED); 217122394Sharti } 218122394Sharti if (asn_get_timeticks(b, &pdu->time_stamp) != ASN_ERR_OK) { 219122394Sharti snmp_error("cannot parse trap 'time-stamp'"); 220122394Sharti return (ASN_ERR_FAILED); 221122394Sharti } 222122394Sharti } else { 223122394Sharti if (asn_get_integer(b, &pdu->request_id) != ASN_ERR_OK) { 224122394Sharti snmp_error("cannot parse 'request-id'"); 225122394Sharti return (ASN_ERR_FAILED); 226122394Sharti } 227122394Sharti if (asn_get_integer(b, &pdu->error_status) != ASN_ERR_OK) { 228122394Sharti snmp_error("cannot parse 'error_status'"); 229122394Sharti return (ASN_ERR_FAILED); 230122394Sharti } 231122394Sharti if (asn_get_integer(b, &pdu->error_index) != ASN_ERR_OK) { 232122394Sharti snmp_error("cannot parse 'error_index'"); 233122394Sharti return (ASN_ERR_FAILED); 234122394Sharti } 235122394Sharti } 236122394Sharti 237122394Sharti if (asn_get_sequence(b, lenp) != ASN_ERR_OK) { 238122394Sharti snmp_error("cannot get varlist header"); 239122394Sharti return (ASN_ERR_FAILED); 240122394Sharti } 241122394Sharti 242122394Sharti return (ASN_ERR_OK); 243122394Sharti} 244122394Sharti 245122394Shartistatic enum asn_err 246122394Shartiparse_pdus(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip) 247122394Sharti{ 248122394Sharti asn_len_t len, trailer; 249122394Sharti struct snmp_value *v; 250122394Sharti enum asn_err err, err1; 251122394Sharti 252122394Sharti err = snmp_parse_pdus_hdr(b, pdu, &len); 253122394Sharti if (ASN_ERR_STOPPED(err)) 254122394Sharti return (err); 255122394Sharti 256122394Sharti trailer = b->asn_len - len; 257122394Sharti 258122394Sharti v = pdu->bindings; 259122394Sharti err = ASN_ERR_OK; 260122394Sharti while (b->asn_len != 0) { 261122394Sharti if (pdu->nbindings == SNMP_MAX_BINDINGS) { 262122394Sharti snmp_error("too many bindings (> %u) in PDU", 263122394Sharti SNMP_MAX_BINDINGS); 264122394Sharti return (ASN_ERR_FAILED); 265122394Sharti } 266122394Sharti err1 = get_var_binding(b, v); 267122394Sharti if (ASN_ERR_STOPPED(err1)) 268122394Sharti return (ASN_ERR_FAILED); 269122394Sharti if (err1 != ASN_ERR_OK && err == ASN_ERR_OK) { 270122394Sharti err = err1; 271122394Sharti *ip = pdu->nbindings + 1; 272122394Sharti } 273122394Sharti pdu->nbindings++; 274122394Sharti v++; 275122394Sharti } 276122394Sharti 277122394Sharti b->asn_len = trailer; 278122394Sharti 279122394Sharti return (err); 280122394Sharti} 281122394Sharti 282216294Ssyrinx 283216294Ssyrinxstatic enum asn_err 284216294Ssyrinxparse_secparams(struct asn_buf *b, struct snmp_pdu *pdu) 285216294Ssyrinx{ 286216294Ssyrinx asn_len_t octs_len; 287216294Ssyrinx u_char buf[256]; /* XXX: calc max possible size here */ 288216294Ssyrinx struct asn_buf tb; 289216294Ssyrinx 290216294Ssyrinx memset(buf, 0, 256); 291216294Ssyrinx tb.asn_ptr = buf; 292216294Ssyrinx tb.asn_len = 256; 293301661Sngie u_int len; 294216294Ssyrinx 295301661Sngie if (asn_get_octetstring(b, buf, &len) != ASN_ERR_OK) { 296216294Ssyrinx snmp_error("cannot parse usm header"); 297216294Ssyrinx return (ASN_ERR_FAILED); 298216294Ssyrinx } 299301661Sngie tb.asn_len = len; 300216294Ssyrinx 301216294Ssyrinx if (asn_get_sequence(&tb, &octs_len) != ASN_ERR_OK) { 302216294Ssyrinx snmp_error("cannot decode usm header"); 303216294Ssyrinx return (ASN_ERR_FAILED); 304216294Ssyrinx } 305216294Ssyrinx 306216294Ssyrinx octs_len = SNMP_ENGINE_ID_SIZ; 307216294Ssyrinx if (asn_get_octetstring(&tb, (u_char *)&pdu->engine.engine_id, 308216294Ssyrinx &octs_len) != ASN_ERR_OK) { 309216294Ssyrinx snmp_error("cannot decode msg engine id"); 310216294Ssyrinx return (ASN_ERR_FAILED); 311216294Ssyrinx } 312216294Ssyrinx pdu->engine.engine_len = octs_len; 313216294Ssyrinx 314216294Ssyrinx if (asn_get_integer(&tb, &pdu->engine.engine_boots) != ASN_ERR_OK) { 315216294Ssyrinx snmp_error("cannot decode msg engine boots"); 316216294Ssyrinx return (ASN_ERR_FAILED); 317216294Ssyrinx } 318216294Ssyrinx 319216294Ssyrinx if (asn_get_integer(&tb, &pdu->engine.engine_time) != ASN_ERR_OK) { 320216294Ssyrinx snmp_error("cannot decode msg engine time"); 321216294Ssyrinx return (ASN_ERR_FAILED); 322216294Ssyrinx } 323216294Ssyrinx 324216294Ssyrinx octs_len = SNMP_ADM_STR32_SIZ - 1; 325216294Ssyrinx if (asn_get_octetstring(&tb, (u_char *)&pdu->user.sec_name, &octs_len) 326216294Ssyrinx != ASN_ERR_OK) { 327216294Ssyrinx snmp_error("cannot decode msg user name"); 328216294Ssyrinx return (ASN_ERR_FAILED); 329216294Ssyrinx } 330216294Ssyrinx pdu->user.sec_name[octs_len] = '\0'; 331216294Ssyrinx 332216294Ssyrinx octs_len = sizeof(pdu->msg_digest); 333216294Ssyrinx if (asn_get_octetstring(&tb, (u_char *)&pdu->msg_digest, &octs_len) != 334216294Ssyrinx ASN_ERR_OK || ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0 && 335216294Ssyrinx octs_len != sizeof(pdu->msg_digest))) { 336216294Ssyrinx snmp_error("cannot decode msg authentication param"); 337216294Ssyrinx return (ASN_ERR_FAILED); 338216294Ssyrinx } 339216294Ssyrinx 340216294Ssyrinx octs_len = sizeof(pdu->msg_salt); 341216294Ssyrinx if (asn_get_octetstring(&tb, (u_char *)&pdu->msg_salt, &octs_len) != 342216294Ssyrinx ASN_ERR_OK ||((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0 && 343216294Ssyrinx octs_len != sizeof(pdu->msg_salt))) { 344216294Ssyrinx snmp_error("cannot decode msg authentication param"); 345216294Ssyrinx return (ASN_ERR_FAILED); 346216294Ssyrinx } 347216294Ssyrinx 348216294Ssyrinx if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) { 349216294Ssyrinx pdu->digest_ptr = b->asn_ptr - SNMP_USM_AUTH_SIZE; 350216294Ssyrinx pdu->digest_ptr -= octs_len + ASN_MAXLENLEN; 351216294Ssyrinx } 352216294Ssyrinx 353216294Ssyrinx return (ASN_ERR_OK); 354216294Ssyrinx} 355216294Ssyrinx 356216294Ssyrinxstatic enum snmp_code 357216294Ssyrinxpdu_encode_secparams(struct asn_buf *b, struct snmp_pdu *pdu) 358216294Ssyrinx{ 359216294Ssyrinx u_char buf[256], *sptr; 360310910Sngie struct asn_buf tb; 361310910Sngie size_t auth_off, moved = 0; 362216294Ssyrinx 363216294Ssyrinx auth_off = 0; 364216294Ssyrinx memset(buf, 0, 256); 365216294Ssyrinx tb.asn_ptr = buf; 366216294Ssyrinx tb.asn_len = 256; 367216294Ssyrinx 368216294Ssyrinx if (asn_put_temp_header(&tb, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED), 369216294Ssyrinx &sptr) != ASN_ERR_OK) 370216294Ssyrinx return (SNMP_CODE_FAILED); 371216294Ssyrinx 372216294Ssyrinx if (asn_put_octetstring(&tb, (u_char *)pdu->engine.engine_id, 373216294Ssyrinx pdu->engine.engine_len) != ASN_ERR_OK) 374216294Ssyrinx return (SNMP_CODE_FAILED); 375216294Ssyrinx 376216294Ssyrinx if (asn_put_integer(&tb, pdu->engine.engine_boots) != ASN_ERR_OK) 377216294Ssyrinx return (SNMP_CODE_FAILED); 378216294Ssyrinx 379216294Ssyrinx if (asn_put_integer(&tb, pdu->engine.engine_time) != ASN_ERR_OK) 380216294Ssyrinx return (SNMP_CODE_FAILED); 381216294Ssyrinx 382216294Ssyrinx if (asn_put_octetstring(&tb, (u_char *)pdu->user.sec_name, 383216294Ssyrinx strlen(pdu->user.sec_name)) != ASN_ERR_OK) 384216294Ssyrinx return (SNMP_CODE_FAILED); 385216294Ssyrinx 386216294Ssyrinx if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) { 387216294Ssyrinx auth_off = sizeof(buf) - tb.asn_len + ASN_MAXLENLEN; 388216294Ssyrinx if (asn_put_octetstring(&tb, (u_char *)pdu->msg_digest, 389216294Ssyrinx sizeof(pdu->msg_digest)) != ASN_ERR_OK) 390216294Ssyrinx return (SNMP_CODE_FAILED); 391216294Ssyrinx } else { 392216294Ssyrinx if (asn_put_octetstring(&tb, (u_char *)pdu->msg_digest, 0) 393216294Ssyrinx != ASN_ERR_OK) 394216294Ssyrinx return (SNMP_CODE_FAILED); 395216294Ssyrinx } 396216294Ssyrinx 397216294Ssyrinx if ((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0) { 398216294Ssyrinx if (asn_put_octetstring(&tb, (u_char *)pdu->msg_salt, 399216294Ssyrinx sizeof(pdu->msg_salt)) != ASN_ERR_OK) 400216294Ssyrinx return (SNMP_CODE_FAILED); 401216294Ssyrinx } else { 402216294Ssyrinx if (asn_put_octetstring(&tb, (u_char *)pdu->msg_salt, 0) 403216294Ssyrinx != ASN_ERR_OK) 404216294Ssyrinx return (SNMP_CODE_FAILED); 405216294Ssyrinx } 406216294Ssyrinx 407216294Ssyrinx if (asn_commit_header(&tb, sptr, &moved) != ASN_ERR_OK) 408216294Ssyrinx return (SNMP_CODE_FAILED); 409216294Ssyrinx 410216294Ssyrinx if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) 411216294Ssyrinx pdu->digest_ptr = b->asn_ptr + auth_off - moved; 412216294Ssyrinx 413216294Ssyrinx if (asn_put_octetstring(b, buf, sizeof(buf) - tb.asn_len) != ASN_ERR_OK) 414216294Ssyrinx return (SNMP_CODE_FAILED); 415216294Ssyrinx pdu->digest_ptr += ASN_MAXLENLEN; 416216294Ssyrinx 417216294Ssyrinx if ((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0 && asn_put_temp_header(b, 418216294Ssyrinx ASN_TYPE_OCTETSTRING, &pdu->encrypted_ptr) != ASN_ERR_OK) 419216294Ssyrinx return (SNMP_CODE_FAILED); 420216294Ssyrinx 421216294Ssyrinx return (SNMP_CODE_OK); 422216294Ssyrinx} 423216294Ssyrinx 424122394Sharti/* 425216294Ssyrinx * Decode the PDU except for the variable bindings itself. 426216294Ssyrinx * If decoding fails because of a bad binding, but the rest can be 427216294Ssyrinx * decoded, ip points to the index of the failed variable (errors 428216294Ssyrinx * OORANGE, BADLEN or BADVERS). 429122394Sharti */ 430216294Ssyrinxenum snmp_code 431216294Ssyrinxsnmp_pdu_decode(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip) 432122394Sharti{ 433216294Ssyrinx enum snmp_code code; 434216294Ssyrinx 435216294Ssyrinx if ((code = snmp_pdu_decode_header(b, pdu)) != SNMP_CODE_OK) 436216294Ssyrinx return (code); 437216294Ssyrinx 438216294Ssyrinx if (pdu->version == SNMP_V3) { 439216294Ssyrinx if (pdu->security_model != SNMP_SECMODEL_USM) 440216294Ssyrinx return (SNMP_CODE_FAILED); 441216294Ssyrinx if ((code = snmp_pdu_decode_secmode(b, pdu)) != SNMP_CODE_OK) 442216294Ssyrinx return (code); 443216294Ssyrinx } 444216294Ssyrinx 445216294Ssyrinx code = snmp_pdu_decode_scoped(b, pdu, ip); 446216294Ssyrinx 447216294Ssyrinx switch (code) { 448216294Ssyrinx case SNMP_CODE_FAILED: 449216294Ssyrinx snmp_pdu_free(pdu); 450216294Ssyrinx break; 451216294Ssyrinx 452216294Ssyrinx case SNMP_CODE_BADENC: 453216294Ssyrinx if (pdu->version == SNMP_Verr) 454216294Ssyrinx return (SNMP_CODE_BADVERS); 455216294Ssyrinx 456216294Ssyrinx default: 457216294Ssyrinx break; 458216294Ssyrinx } 459216294Ssyrinx 460216294Ssyrinx return (code); 461216294Ssyrinx} 462216294Ssyrinx 463216294Ssyrinxenum snmp_code 464216294Ssyrinxsnmp_pdu_decode_header(struct asn_buf *b, struct snmp_pdu *pdu) 465216294Ssyrinx{ 466122394Sharti int32_t version; 467216294Ssyrinx u_int octs_len; 468216294Ssyrinx asn_len_t len; 469122394Sharti 470216294Ssyrinx pdu->outer_ptr = b->asn_ptr; 471216294Ssyrinx pdu->outer_len = b->asn_len; 472216294Ssyrinx 473216294Ssyrinx if (asn_get_sequence(b, &len) != ASN_ERR_OK) { 474216294Ssyrinx snmp_error("cannot decode pdu header"); 475216294Ssyrinx return (SNMP_CODE_FAILED); 476216294Ssyrinx } 477216294Ssyrinx if (b->asn_len < len) { 478216294Ssyrinx snmp_error("outer sequence value too short"); 479216294Ssyrinx return (SNMP_CODE_FAILED); 480216294Ssyrinx } 481216294Ssyrinx if (b->asn_len != len) { 482216294Ssyrinx snmp_error("ignoring trailing junk in message"); 483216294Ssyrinx b->asn_len = len; 484216294Ssyrinx } 485216294Ssyrinx 486122394Sharti if (asn_get_integer(b, &version) != ASN_ERR_OK) { 487122394Sharti snmp_error("cannot decode version"); 488216294Ssyrinx return (SNMP_CODE_FAILED); 489122394Sharti } 490122394Sharti 491216294Ssyrinx if (version == 0) 492122394Sharti pdu->version = SNMP_V1; 493216294Ssyrinx else if (version == 1) 494122394Sharti pdu->version = SNMP_V2c; 495216294Ssyrinx else if (version == 3) 496216294Ssyrinx pdu->version = SNMP_V3; 497216294Ssyrinx else { 498122394Sharti pdu->version = SNMP_Verr; 499122394Sharti snmp_error("unsupported SNMP version"); 500216294Ssyrinx return (SNMP_CODE_BADENC); 501122394Sharti } 502122394Sharti 503216294Ssyrinx if (pdu->version == SNMP_V3) { 504216294Ssyrinx if (asn_get_sequence(b, &len) != ASN_ERR_OK) { 505216294Ssyrinx snmp_error("cannot decode pdu global data header"); 506216294Ssyrinx return (SNMP_CODE_FAILED); 507216294Ssyrinx } 508216294Ssyrinx 509216294Ssyrinx if (asn_get_integer(b, &pdu->identifier) != ASN_ERR_OK) { 510216294Ssyrinx snmp_error("cannot decode msg indetifier"); 511216294Ssyrinx return (SNMP_CODE_FAILED); 512216294Ssyrinx } 513216294Ssyrinx 514216294Ssyrinx if (asn_get_integer(b, &pdu->engine.max_msg_size) 515216294Ssyrinx != ASN_ERR_OK) { 516216294Ssyrinx snmp_error("cannot decode msg size"); 517216294Ssyrinx return (SNMP_CODE_FAILED); 518216294Ssyrinx } 519216294Ssyrinx 520216294Ssyrinx octs_len = 1; 521216294Ssyrinx if (asn_get_octetstring(b, (u_char *)&pdu->flags, 522216294Ssyrinx &octs_len) != ASN_ERR_OK) { 523216294Ssyrinx snmp_error("cannot decode msg flags"); 524216294Ssyrinx return (SNMP_CODE_FAILED); 525216294Ssyrinx } 526216294Ssyrinx 527216294Ssyrinx if (asn_get_integer(b, &pdu->security_model) != ASN_ERR_OK) { 528216294Ssyrinx snmp_error("cannot decode msg size"); 529216294Ssyrinx return (SNMP_CODE_FAILED); 530216294Ssyrinx } 531216294Ssyrinx 532216294Ssyrinx if (pdu->security_model != SNMP_SECMODEL_USM) 533216294Ssyrinx return (SNMP_CODE_FAILED); 534216294Ssyrinx 535216294Ssyrinx if (parse_secparams(b, pdu) != ASN_ERR_OK) 536216294Ssyrinx return (SNMP_CODE_FAILED); 537216294Ssyrinx } else { 538216294Ssyrinx octs_len = SNMP_COMMUNITY_MAXLEN; 539216294Ssyrinx if (asn_get_octetstring(b, (u_char *)pdu->community, 540216294Ssyrinx &octs_len) != ASN_ERR_OK) { 541216294Ssyrinx snmp_error("cannot decode community"); 542216294Ssyrinx return (SNMP_CODE_FAILED); 543216294Ssyrinx } 544216294Ssyrinx pdu->community[octs_len] = '\0'; 545122394Sharti } 546122394Sharti 547216294Ssyrinx return (SNMP_CODE_OK); 548216294Ssyrinx} 549216294Ssyrinx 550216294Ssyrinxenum snmp_code 551216294Ssyrinxsnmp_pdu_decode_scoped(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip) 552216294Ssyrinx{ 553216294Ssyrinx u_char type; 554216294Ssyrinx asn_len_t len, trailer; 555216294Ssyrinx enum asn_err err; 556216294Ssyrinx 557216294Ssyrinx if (pdu->version == SNMP_V3) { 558216294Ssyrinx if (asn_get_sequence(b, &len) != ASN_ERR_OK) { 559216294Ssyrinx snmp_error("cannot decode scoped pdu header"); 560216294Ssyrinx return (SNMP_CODE_FAILED); 561216294Ssyrinx } 562216294Ssyrinx 563216294Ssyrinx len = SNMP_ENGINE_ID_SIZ; 564216294Ssyrinx if (asn_get_octetstring(b, (u_char *)&pdu->context_engine, 565216294Ssyrinx &len) != ASN_ERR_OK) { 566216294Ssyrinx snmp_error("cannot decode msg context engine"); 567216294Ssyrinx return (SNMP_CODE_FAILED); 568216294Ssyrinx } 569216294Ssyrinx pdu->context_engine_len = len; 570216294Ssyrinx 571216294Ssyrinx len = SNMP_CONTEXT_NAME_SIZ; 572216294Ssyrinx if (asn_get_octetstring(b, (u_char *)&pdu->context_name, 573216294Ssyrinx &len) != ASN_ERR_OK) { 574216294Ssyrinx snmp_error("cannot decode msg context name"); 575216294Ssyrinx return (SNMP_CODE_FAILED); 576216294Ssyrinx } 577216294Ssyrinx pdu->context_name[len] = '\0'; 578216294Ssyrinx } 579216294Ssyrinx 580216294Ssyrinx if (asn_get_header(b, &type, &len) != ASN_ERR_OK) { 581122394Sharti snmp_error("cannot get pdu header"); 582216294Ssyrinx return (SNMP_CODE_FAILED); 583122394Sharti } 584122394Sharti if ((type & ~ASN_TYPE_MASK) != 585122394Sharti (ASN_TYPE_CONSTRUCTED | ASN_CLASS_CONTEXT)) { 586122394Sharti snmp_error("bad pdu header tag"); 587216294Ssyrinx return (SNMP_CODE_FAILED); 588122394Sharti } 589122394Sharti pdu->type = type & ASN_TYPE_MASK; 590122394Sharti 591122394Sharti switch (pdu->type) { 592122394Sharti 593122394Sharti case SNMP_PDU_GET: 594122394Sharti case SNMP_PDU_GETNEXT: 595122394Sharti case SNMP_PDU_RESPONSE: 596122394Sharti case SNMP_PDU_SET: 597122394Sharti break; 598122394Sharti 599122394Sharti case SNMP_PDU_TRAP: 600122394Sharti if (pdu->version != SNMP_V1) { 601122394Sharti snmp_error("bad pdu type %u", pdu->type); 602216294Ssyrinx return (SNMP_CODE_FAILED); 603122394Sharti } 604122394Sharti break; 605122394Sharti 606122394Sharti case SNMP_PDU_GETBULK: 607122394Sharti case SNMP_PDU_INFORM: 608122394Sharti case SNMP_PDU_TRAP2: 609122394Sharti case SNMP_PDU_REPORT: 610122394Sharti if (pdu->version == SNMP_V1) { 611122394Sharti snmp_error("bad pdu type %u", pdu->type); 612216294Ssyrinx return (SNMP_CODE_FAILED); 613122394Sharti } 614122394Sharti break; 615122394Sharti 616122394Sharti default: 617122394Sharti snmp_error("bad pdu type %u", pdu->type); 618216294Ssyrinx return (SNMP_CODE_FAILED); 619122394Sharti } 620122394Sharti 621122394Sharti trailer = b->asn_len - len; 622122394Sharti b->asn_len = len; 623122394Sharti 624122394Sharti err = parse_pdus(b, pdu, ip); 625122394Sharti if (ASN_ERR_STOPPED(err)) 626216294Ssyrinx return (SNMP_CODE_FAILED); 627122394Sharti 628122394Sharti if (b->asn_len != 0) 629122394Sharti snmp_error("ignoring trailing junk after pdu"); 630122394Sharti 631122394Sharti b->asn_len = trailer; 632122394Sharti 633216294Ssyrinx return (SNMP_CODE_OK); 634122394Sharti} 635122394Sharti 636122394Shartienum snmp_code 637216294Ssyrinxsnmp_pdu_decode_secmode(struct asn_buf *b, struct snmp_pdu *pdu) 638122394Sharti{ 639216294Ssyrinx u_char type; 640216294Ssyrinx enum snmp_code code; 641216294Ssyrinx uint8_t digest[SNMP_USM_AUTH_SIZE]; 642122394Sharti 643216294Ssyrinx if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH && 644216294Ssyrinx (pdu->flags & SNMP_MSG_AUTH_FLAG) == 0) 645216294Ssyrinx return (SNMP_CODE_BADSECLEVEL); 646122394Sharti 647216482Ssyrinx if ((code = snmp_pdu_calc_digest(pdu, digest)) != 648216294Ssyrinx SNMP_CODE_OK) 649122394Sharti return (SNMP_CODE_FAILED); 650216294Ssyrinx 651216294Ssyrinx if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH && 652216294Ssyrinx memcmp(digest, pdu->msg_digest, sizeof(pdu->msg_digest)) != 0) 653216294Ssyrinx return (SNMP_CODE_BADDIGEST); 654216294Ssyrinx 655216294Ssyrinx if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV && (asn_get_header(b, &type, 656216294Ssyrinx &pdu->scoped_len) != ASN_ERR_OK || type != ASN_TYPE_OCTETSTRING)) { 657216294Ssyrinx snmp_error("cannot decode encrypted pdu"); 658122394Sharti return (SNMP_CODE_FAILED); 659122394Sharti } 660216294Ssyrinx pdu->scoped_ptr = b->asn_ptr; 661122394Sharti 662216294Ssyrinx if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV && 663216294Ssyrinx (pdu->flags & SNMP_MSG_PRIV_FLAG) == 0) 664216294Ssyrinx return (SNMP_CODE_BADSECLEVEL); 665122394Sharti 666216482Ssyrinx if ((code = snmp_pdu_decrypt(pdu)) != SNMP_CODE_OK) 667122394Sharti return (SNMP_CODE_FAILED); 668122394Sharti 669216294Ssyrinx return (code); 670122394Sharti} 671122394Sharti 672122394Sharti/* 673124861Sharti * Check whether what we have is the complete PDU by snooping at the 674124861Sharti * enclosing structure header. This returns: 675124861Sharti * -1 if there are ASN.1 errors 676124861Sharti * 0 if we need more data 677124861Sharti * > 0 the length of this PDU 678124861Sharti */ 679124861Shartiint 680124861Shartisnmp_pdu_snoop(const struct asn_buf *b0) 681124861Sharti{ 682124861Sharti u_int length; 683124861Sharti asn_len_t len; 684124861Sharti struct asn_buf b = *b0; 685124861Sharti 686124861Sharti /* <0x10|0x20> <len> <data...> */ 687310903Sngie 688124861Sharti if (b.asn_len == 0) 689124861Sharti return (0); 690124861Sharti if (b.asn_cptr[0] != (ASN_TYPE_SEQUENCE | ASN_TYPE_CONSTRUCTED)) { 691124861Sharti asn_error(&b, "bad sequence type %u", b.asn_cptr[0]); 692124861Sharti return (-1); 693124861Sharti } 694124861Sharti b.asn_len--; 695124861Sharti b.asn_cptr++; 696124861Sharti 697124861Sharti if (b.asn_len == 0) 698124861Sharti return (0); 699124861Sharti 700124861Sharti if (*b.asn_cptr & 0x80) { 701124861Sharti /* long length */ 702124861Sharti length = *b.asn_cptr++ & 0x7f; 703124861Sharti b.asn_len--; 704124861Sharti if (length == 0) { 705124861Sharti asn_error(&b, "indefinite length not supported"); 706124861Sharti return (-1); 707124861Sharti } 708124861Sharti if (length > ASN_MAXLENLEN) { 709124861Sharti asn_error(&b, "long length too long (%u)", length); 710124861Sharti return (-1); 711124861Sharti } 712124861Sharti if (length > b.asn_len) 713124861Sharti return (0); 714124861Sharti len = 0; 715124861Sharti while (length--) { 716124861Sharti len = (len << 8) | *b.asn_cptr++; 717124861Sharti b.asn_len--; 718124861Sharti } 719124861Sharti } else { 720124861Sharti len = *b.asn_cptr++; 721124861Sharti b.asn_len--; 722124861Sharti } 723124861Sharti 724124861Sharti if (len > b.asn_len) 725124861Sharti return (0); 726124861Sharti 727124861Sharti return (len + b.asn_cptr - b0->asn_cptr); 728124861Sharti} 729124861Sharti 730124861Sharti/* 731122394Sharti * Encode the SNMP PDU without the variable bindings field. 732122394Sharti * We do this the rather uneffective way by 733122394Sharti * moving things around and assuming that the length field will never 734122394Sharti * use more than 2 bytes. 735122394Sharti * We need a number of pointers to apply the fixes afterwards. 736122394Sharti */ 737122394Shartienum snmp_code 738122394Shartisnmp_pdu_encode_header(struct asn_buf *b, struct snmp_pdu *pdu) 739122394Sharti{ 740122394Sharti enum asn_err err; 741216294Ssyrinx u_char *v3_hdr_ptr; 742122394Sharti 743122394Sharti if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED), 744122394Sharti &pdu->outer_ptr) != ASN_ERR_OK) 745122394Sharti return (SNMP_CODE_FAILED); 746122394Sharti 747122394Sharti if (pdu->version == SNMP_V1) 748122394Sharti err = asn_put_integer(b, 0); 749122394Sharti else if (pdu->version == SNMP_V2c) 750122394Sharti err = asn_put_integer(b, 1); 751216294Ssyrinx else if (pdu->version == SNMP_V3) 752216294Ssyrinx err = asn_put_integer(b, 3); 753122394Sharti else 754122394Sharti return (SNMP_CODE_BADVERS); 755122394Sharti if (err != ASN_ERR_OK) 756122394Sharti return (SNMP_CODE_FAILED); 757122394Sharti 758216294Ssyrinx if (pdu->version == SNMP_V3) { 759216294Ssyrinx if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE | 760216294Ssyrinx ASN_TYPE_CONSTRUCTED), &v3_hdr_ptr) != ASN_ERR_OK) 761216294Ssyrinx return (SNMP_CODE_FAILED); 762310903Sngie 763216294Ssyrinx if (asn_put_integer(b, pdu->identifier) != ASN_ERR_OK) 764216294Ssyrinx return (SNMP_CODE_FAILED); 765122394Sharti 766216294Ssyrinx if (asn_put_integer(b, pdu->engine.max_msg_size) != ASN_ERR_OK) 767216294Ssyrinx return (SNMP_CODE_FAILED); 768216294Ssyrinx 769216294Ssyrinx if (pdu->type != SNMP_PDU_RESPONSE && 770216294Ssyrinx pdu->type != SNMP_PDU_TRAP && 771216594Ssyrinx pdu->type != SNMP_PDU_TRAP2 && 772216294Ssyrinx pdu->type != SNMP_PDU_REPORT) 773216294Ssyrinx pdu->flags |= SNMP_MSG_REPORT_FLAG; 774216294Ssyrinx 775216294Ssyrinx if (asn_put_octetstring(b, (u_char *)&pdu->flags, 1) 776216294Ssyrinx != ASN_ERR_OK) 777216294Ssyrinx return (SNMP_CODE_FAILED); 778216294Ssyrinx 779216294Ssyrinx if (asn_put_integer(b, pdu->security_model) != ASN_ERR_OK) 780216294Ssyrinx return (SNMP_CODE_FAILED); 781216294Ssyrinx 782216294Ssyrinx if (asn_commit_header(b, v3_hdr_ptr, NULL) != ASN_ERR_OK) 783216294Ssyrinx return (SNMP_CODE_FAILED); 784216294Ssyrinx 785216294Ssyrinx if (pdu->security_model != SNMP_SECMODEL_USM) 786216294Ssyrinx return (SNMP_CODE_FAILED); 787216294Ssyrinx 788216294Ssyrinx if (pdu_encode_secparams(b, pdu) != SNMP_CODE_OK) 789216294Ssyrinx return (SNMP_CODE_FAILED); 790216294Ssyrinx 791216294Ssyrinx /* View-based Access Conntrol information */ 792216294Ssyrinx if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE | 793216294Ssyrinx ASN_TYPE_CONSTRUCTED), &pdu->scoped_ptr) != ASN_ERR_OK) 794216294Ssyrinx return (SNMP_CODE_FAILED); 795216294Ssyrinx 796216294Ssyrinx if (asn_put_octetstring(b, (u_char *)pdu->context_engine, 797216294Ssyrinx pdu->context_engine_len) != ASN_ERR_OK) 798216294Ssyrinx return (SNMP_CODE_FAILED); 799216294Ssyrinx 800216294Ssyrinx if (asn_put_octetstring(b, (u_char *)pdu->context_name, 801216294Ssyrinx strlen(pdu->context_name)) != ASN_ERR_OK) 802216294Ssyrinx return (SNMP_CODE_FAILED); 803216294Ssyrinx } else { 804216294Ssyrinx if (asn_put_octetstring(b, (u_char *)pdu->community, 805216294Ssyrinx strlen(pdu->community)) != ASN_ERR_OK) 806216294Ssyrinx return (SNMP_CODE_FAILED); 807216294Ssyrinx } 808216294Ssyrinx 809122394Sharti if (asn_put_temp_header(b, (ASN_TYPE_CONSTRUCTED | ASN_CLASS_CONTEXT | 810122394Sharti pdu->type), &pdu->pdu_ptr) != ASN_ERR_OK) 811122394Sharti return (SNMP_CODE_FAILED); 812122394Sharti 813122394Sharti if (pdu->type == SNMP_PDU_TRAP) { 814122394Sharti if (pdu->version != SNMP_V1 || 815122394Sharti asn_put_objid(b, &pdu->enterprise) != ASN_ERR_OK || 816122394Sharti asn_put_ipaddress(b, pdu->agent_addr) != ASN_ERR_OK || 817122394Sharti asn_put_integer(b, pdu->generic_trap) != ASN_ERR_OK || 818122394Sharti asn_put_integer(b, pdu->specific_trap) != ASN_ERR_OK || 819122394Sharti asn_put_timeticks(b, pdu->time_stamp) != ASN_ERR_OK) 820122394Sharti return (SNMP_CODE_FAILED); 821122394Sharti } else { 822122394Sharti if (pdu->version == SNMP_V1 && (pdu->type == SNMP_PDU_GETBULK || 823122394Sharti pdu->type == SNMP_PDU_INFORM || 824122394Sharti pdu->type == SNMP_PDU_TRAP2 || 825122394Sharti pdu->type == SNMP_PDU_REPORT)) 826122394Sharti return (SNMP_CODE_FAILED); 827122394Sharti 828122394Sharti if (asn_put_integer(b, pdu->request_id) != ASN_ERR_OK || 829122394Sharti asn_put_integer(b, pdu->error_status) != ASN_ERR_OK || 830122394Sharti asn_put_integer(b, pdu->error_index) != ASN_ERR_OK) 831122394Sharti return (SNMP_CODE_FAILED); 832122394Sharti } 833122394Sharti 834122394Sharti if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED), 835122394Sharti &pdu->vars_ptr) != ASN_ERR_OK) 836122394Sharti return (SNMP_CODE_FAILED); 837122394Sharti 838122394Sharti return (SNMP_CODE_OK); 839122394Sharti} 840122394Sharti 841216294Ssyrinxstatic enum asn_err 842216294Ssyrinxsnmp_pdu_fix_padd(struct asn_buf *b, struct snmp_pdu *pdu) 843216294Ssyrinx{ 844216294Ssyrinx asn_len_t padlen; 845216294Ssyrinx 846216294Ssyrinx if (pdu->user.priv_proto == SNMP_PRIV_DES && pdu->scoped_len % 8 != 0) { 847216294Ssyrinx padlen = 8 - (pdu->scoped_len % 8); 848216294Ssyrinx if (asn_pad(b, padlen) != ASN_ERR_OK) 849216294Ssyrinx return (ASN_ERR_FAILED); 850216294Ssyrinx pdu->scoped_len += padlen; 851216294Ssyrinx } 852216294Ssyrinx 853216294Ssyrinx return (ASN_ERR_OK); 854216294Ssyrinx} 855216294Ssyrinx 856122394Shartienum snmp_code 857216294Ssyrinxsnmp_fix_encoding(struct asn_buf *b, struct snmp_pdu *pdu) 858122394Sharti{ 859216294Ssyrinx size_t moved = 0; 860216294Ssyrinx enum snmp_code code; 861216294Ssyrinx 862216294Ssyrinx if (asn_commit_header(b, pdu->vars_ptr, NULL) != ASN_ERR_OK || 863216294Ssyrinx asn_commit_header(b, pdu->pdu_ptr, NULL) != ASN_ERR_OK) 864122394Sharti return (SNMP_CODE_FAILED); 865216294Ssyrinx 866216294Ssyrinx if (pdu->version == SNMP_V3) { 867216294Ssyrinx if (asn_commit_header(b, pdu->scoped_ptr, NULL) != ASN_ERR_OK) 868216294Ssyrinx return (SNMP_CODE_FAILED); 869216294Ssyrinx 870216294Ssyrinx pdu->scoped_len = b->asn_ptr - pdu->scoped_ptr; 871301661Sngie if (snmp_pdu_fix_padd(b, pdu) != ASN_ERR_OK) 872216294Ssyrinx return (SNMP_CODE_FAILED); 873216294Ssyrinx 874216294Ssyrinx if (pdu->security_model != SNMP_SECMODEL_USM) 875216294Ssyrinx return (SNMP_CODE_FAILED); 876216294Ssyrinx 877216482Ssyrinx if (snmp_pdu_encrypt(pdu) != SNMP_CODE_OK) 878216294Ssyrinx return (SNMP_CODE_FAILED); 879216294Ssyrinx 880216294Ssyrinx if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV && 881216294Ssyrinx asn_commit_header(b, pdu->encrypted_ptr, NULL) != ASN_ERR_OK) 882216294Ssyrinx return (SNMP_CODE_FAILED); 883216294Ssyrinx } 884216294Ssyrinx 885216294Ssyrinx if (asn_commit_header(b, pdu->outer_ptr, &moved) != ASN_ERR_OK) 886216294Ssyrinx return (SNMP_CODE_FAILED); 887216294Ssyrinx 888216294Ssyrinx pdu->outer_len = b->asn_ptr - pdu->outer_ptr; 889216294Ssyrinx pdu->digest_ptr -= moved; 890216294Ssyrinx 891216294Ssyrinx if (pdu->version == SNMP_V3) { 892216482Ssyrinx if ((code = snmp_pdu_calc_digest(pdu, pdu->msg_digest)) != 893216294Ssyrinx SNMP_CODE_OK) 894216294Ssyrinx return (SNMP_CODE_FAILED); 895216294Ssyrinx 896216294Ssyrinx if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) 897216294Ssyrinx memcpy(pdu->digest_ptr, pdu->msg_digest, 898216294Ssyrinx sizeof(pdu->msg_digest)); 899216294Ssyrinx } 900216294Ssyrinx 901122394Sharti return (SNMP_CODE_OK); 902122394Sharti} 903122394Sharti 904122394Sharti/* 905122394Sharti * Encode a binding. Caller must ensure, that the syntax is ok for that version. 906122394Sharti * Be sure not to cobber b, when something fails. 907122394Sharti */ 908122394Shartienum asn_err 909122394Shartisnmp_binding_encode(struct asn_buf *b, const struct snmp_value *binding) 910122394Sharti{ 911122394Sharti u_char *ptr; 912122394Sharti enum asn_err err; 913122394Sharti struct asn_buf save = *b; 914122394Sharti 915122394Sharti if ((err = asn_put_temp_header(b, (ASN_TYPE_SEQUENCE | 916122394Sharti ASN_TYPE_CONSTRUCTED), &ptr)) != ASN_ERR_OK) { 917122394Sharti *b = save; 918122394Sharti return (err); 919122394Sharti } 920122394Sharti 921122394Sharti if ((err = asn_put_objid(b, &binding->var)) != ASN_ERR_OK) { 922122394Sharti *b = save; 923122394Sharti return (err); 924122394Sharti } 925122394Sharti 926122394Sharti switch (binding->syntax) { 927122394Sharti 928122394Sharti case SNMP_SYNTAX_NULL: 929122394Sharti err = asn_put_null(b); 930122394Sharti break; 931122394Sharti 932122394Sharti case SNMP_SYNTAX_INTEGER: 933122394Sharti err = asn_put_integer(b, binding->v.integer); 934122394Sharti break; 935122394Sharti 936122394Sharti case SNMP_SYNTAX_OCTETSTRING: 937122394Sharti err = asn_put_octetstring(b, binding->v.octetstring.octets, 938122394Sharti binding->v.octetstring.len); 939122394Sharti break; 940122394Sharti 941122394Sharti case SNMP_SYNTAX_OID: 942122394Sharti err = asn_put_objid(b, &binding->v.oid); 943122394Sharti break; 944122394Sharti 945122394Sharti case SNMP_SYNTAX_IPADDRESS: 946122394Sharti err = asn_put_ipaddress(b, binding->v.ipaddress); 947122394Sharti break; 948122394Sharti 949122394Sharti case SNMP_SYNTAX_TIMETICKS: 950122394Sharti err = asn_put_uint32(b, ASN_APP_TIMETICKS, binding->v.uint32); 951122394Sharti break; 952122394Sharti 953122394Sharti case SNMP_SYNTAX_COUNTER: 954122394Sharti err = asn_put_uint32(b, ASN_APP_COUNTER, binding->v.uint32); 955122394Sharti break; 956122394Sharti 957122394Sharti case SNMP_SYNTAX_GAUGE: 958122394Sharti err = asn_put_uint32(b, ASN_APP_GAUGE, binding->v.uint32); 959122394Sharti break; 960122394Sharti 961122394Sharti case SNMP_SYNTAX_COUNTER64: 962122394Sharti err = asn_put_counter64(b, binding->v.counter64); 963122394Sharti break; 964122394Sharti 965122394Sharti case SNMP_SYNTAX_NOSUCHOBJECT: 966122394Sharti err = asn_put_exception(b, ASN_EXCEPT_NOSUCHOBJECT); 967122394Sharti break; 968122394Sharti 969122394Sharti case SNMP_SYNTAX_NOSUCHINSTANCE: 970122394Sharti err = asn_put_exception(b, ASN_EXCEPT_NOSUCHINSTANCE); 971122394Sharti break; 972122394Sharti 973122394Sharti case SNMP_SYNTAX_ENDOFMIBVIEW: 974122394Sharti err = asn_put_exception(b, ASN_EXCEPT_ENDOFMIBVIEW); 975122394Sharti break; 976122394Sharti } 977122394Sharti 978122394Sharti if (err != ASN_ERR_OK) { 979122394Sharti *b = save; 980122394Sharti return (err); 981122394Sharti } 982122394Sharti 983216294Ssyrinx err = asn_commit_header(b, ptr, NULL); 984122394Sharti if (err != ASN_ERR_OK) { 985122394Sharti *b = save; 986122394Sharti return (err); 987122394Sharti } 988122394Sharti 989122394Sharti return (ASN_ERR_OK); 990122394Sharti} 991122394Sharti 992122394Sharti/* 993122394Sharti * Encode an PDU. 994122394Sharti */ 995122394Shartienum snmp_code 996122394Shartisnmp_pdu_encode(struct snmp_pdu *pdu, struct asn_buf *resp_b) 997122394Sharti{ 998122394Sharti u_int idx; 999122394Sharti enum snmp_code err; 1000122394Sharti 1001122394Sharti if ((err = snmp_pdu_encode_header(resp_b, pdu)) != SNMP_CODE_OK) 1002122394Sharti return (err); 1003122394Sharti for (idx = 0; idx < pdu->nbindings; idx++) 1004301661Sngie if (snmp_binding_encode(resp_b, &pdu->bindings[idx]) 1005122394Sharti != ASN_ERR_OK) 1006122394Sharti return (SNMP_CODE_FAILED); 1007122394Sharti 1008122394Sharti return (snmp_fix_encoding(resp_b, pdu)); 1009122394Sharti} 1010122394Sharti 1011122394Shartistatic void 1012122394Shartidump_binding(const struct snmp_value *b) 1013122394Sharti{ 1014122394Sharti u_int i; 1015122394Sharti char buf[ASN_OIDSTRLEN]; 1016122394Sharti 1017122394Sharti snmp_printf("%s=", asn_oid2str_r(&b->var, buf)); 1018122394Sharti switch (b->syntax) { 1019122394Sharti 1020122394Sharti case SNMP_SYNTAX_NULL: 1021122394Sharti snmp_printf("NULL"); 1022122394Sharti break; 1023122394Sharti 1024122394Sharti case SNMP_SYNTAX_INTEGER: 1025122394Sharti snmp_printf("INTEGER %d", b->v.integer); 1026122394Sharti break; 1027122394Sharti 1028122394Sharti case SNMP_SYNTAX_OCTETSTRING: 1029122394Sharti snmp_printf("OCTET STRING %lu:", b->v.octetstring.len); 1030122394Sharti for (i = 0; i < b->v.octetstring.len; i++) 1031122394Sharti snmp_printf(" %02x", b->v.octetstring.octets[i]); 1032122394Sharti break; 1033122394Sharti 1034122394Sharti case SNMP_SYNTAX_OID: 1035122394Sharti snmp_printf("OID %s", asn_oid2str_r(&b->v.oid, buf)); 1036122394Sharti break; 1037122394Sharti 1038122394Sharti case SNMP_SYNTAX_IPADDRESS: 1039122394Sharti snmp_printf("IPADDRESS %u.%u.%u.%u", b->v.ipaddress[0], 1040122394Sharti b->v.ipaddress[1], b->v.ipaddress[2], b->v.ipaddress[3]); 1041122394Sharti break; 1042122394Sharti 1043122394Sharti case SNMP_SYNTAX_COUNTER: 1044122394Sharti snmp_printf("COUNTER %u", b->v.uint32); 1045122394Sharti break; 1046122394Sharti 1047122394Sharti case SNMP_SYNTAX_GAUGE: 1048122394Sharti snmp_printf("GAUGE %u", b->v.uint32); 1049122394Sharti break; 1050122394Sharti 1051122394Sharti case SNMP_SYNTAX_TIMETICKS: 1052122394Sharti snmp_printf("TIMETICKS %u", b->v.uint32); 1053122394Sharti break; 1054122394Sharti 1055122394Sharti case SNMP_SYNTAX_COUNTER64: 1056122394Sharti snmp_printf("COUNTER64 %lld", b->v.counter64); 1057122394Sharti break; 1058122394Sharti 1059122394Sharti case SNMP_SYNTAX_NOSUCHOBJECT: 1060122394Sharti snmp_printf("NoSuchObject"); 1061122394Sharti break; 1062122394Sharti 1063122394Sharti case SNMP_SYNTAX_NOSUCHINSTANCE: 1064122394Sharti snmp_printf("NoSuchInstance"); 1065122394Sharti break; 1066122394Sharti 1067122394Sharti case SNMP_SYNTAX_ENDOFMIBVIEW: 1068122394Sharti snmp_printf("EndOfMibView"); 1069122394Sharti break; 1070122394Sharti 1071122394Sharti default: 1072122394Sharti snmp_printf("UNKNOWN SYNTAX %u", b->syntax); 1073122394Sharti break; 1074122394Sharti } 1075122394Sharti} 1076122394Sharti 1077122394Shartistatic __inline void 1078122394Shartidump_bindings(const struct snmp_pdu *pdu) 1079122394Sharti{ 1080122394Sharti u_int i; 1081122394Sharti 1082122394Sharti for (i = 0; i < pdu->nbindings; i++) { 1083122394Sharti snmp_printf(" [%u]: ", i); 1084122394Sharti dump_binding(&pdu->bindings[i]); 1085122394Sharti snmp_printf("\n"); 1086122394Sharti } 1087122394Sharti} 1088122394Sharti 1089122394Shartistatic __inline void 1090122394Shartidump_notrap(const struct snmp_pdu *pdu) 1091122394Sharti{ 1092122394Sharti snmp_printf(" request_id=%d", pdu->request_id); 1093122394Sharti snmp_printf(" error_status=%d", pdu->error_status); 1094122394Sharti snmp_printf(" error_index=%d\n", pdu->error_index); 1095122394Sharti dump_bindings(pdu); 1096122394Sharti} 1097122394Sharti 1098122394Shartivoid 1099122394Shartisnmp_pdu_dump(const struct snmp_pdu *pdu) 1100122394Sharti{ 1101122394Sharti char buf[ASN_OIDSTRLEN]; 1102122394Sharti const char *vers; 1103122394Sharti static const char *types[] = { 1104122394Sharti [SNMP_PDU_GET] = "GET", 1105122394Sharti [SNMP_PDU_GETNEXT] = "GETNEXT", 1106122394Sharti [SNMP_PDU_RESPONSE] = "RESPONSE", 1107122394Sharti [SNMP_PDU_SET] = "SET", 1108122394Sharti [SNMP_PDU_TRAP] = "TRAPv1", 1109122394Sharti [SNMP_PDU_GETBULK] = "GETBULK", 1110122394Sharti [SNMP_PDU_INFORM] = "INFORM", 1111122394Sharti [SNMP_PDU_TRAP2] = "TRAPv2", 1112122394Sharti [SNMP_PDU_REPORT] = "REPORT", 1113122394Sharti }; 1114122394Sharti 1115122394Sharti if (pdu->version == SNMP_V1) 1116122394Sharti vers = "SNMPv1"; 1117122394Sharti else if (pdu->version == SNMP_V2c) 1118122394Sharti vers = "SNMPv2c"; 1119216294Ssyrinx else if (pdu->version == SNMP_V3) 1120216294Ssyrinx vers = "SNMPv3"; 1121122394Sharti else 1122122394Sharti vers = "v?"; 1123122394Sharti 1124122394Sharti switch (pdu->type) { 1125122394Sharti case SNMP_PDU_TRAP: 1126122394Sharti snmp_printf("%s %s '%s'", types[pdu->type], vers, pdu->community); 1127122394Sharti snmp_printf(" enterprise=%s", asn_oid2str_r(&pdu->enterprise, buf)); 1128122394Sharti snmp_printf(" agent_addr=%u.%u.%u.%u", pdu->agent_addr[0], 1129122394Sharti pdu->agent_addr[1], pdu->agent_addr[2], pdu->agent_addr[3]); 1130122394Sharti snmp_printf(" generic_trap=%d", pdu->generic_trap); 1131122394Sharti snmp_printf(" specific_trap=%d", pdu->specific_trap); 1132122394Sharti snmp_printf(" time-stamp=%u\n", pdu->time_stamp); 1133122394Sharti dump_bindings(pdu); 1134122394Sharti break; 1135122394Sharti 1136122394Sharti case SNMP_PDU_GET: 1137122394Sharti case SNMP_PDU_GETNEXT: 1138122394Sharti case SNMP_PDU_RESPONSE: 1139122394Sharti case SNMP_PDU_SET: 1140122394Sharti case SNMP_PDU_GETBULK: 1141122394Sharti case SNMP_PDU_INFORM: 1142122394Sharti case SNMP_PDU_TRAP2: 1143122394Sharti case SNMP_PDU_REPORT: 1144122394Sharti snmp_printf("%s %s '%s'", types[pdu->type], vers, pdu->community); 1145122394Sharti dump_notrap(pdu); 1146122394Sharti break; 1147122394Sharti 1148122394Sharti default: 1149122394Sharti snmp_printf("bad pdu type %u\n", pdu->type); 1150122394Sharti break; 1151122394Sharti } 1152122394Sharti} 1153122394Sharti 1154122394Shartivoid 1155122394Shartisnmp_value_free(struct snmp_value *value) 1156122394Sharti{ 1157312047Sngie 1158312047Sngie if (value->syntax == SNMP_SYNTAX_OCTETSTRING) { 1159122394Sharti free(value->v.octetstring.octets); 1160312047Sngie value->v.octetstring.octets = NULL; 1161312047Sngie } 1162122394Sharti value->syntax = SNMP_SYNTAX_NULL; 1163122394Sharti} 1164122394Sharti 1165122394Shartiint 1166122394Shartisnmp_value_copy(struct snmp_value *to, const struct snmp_value *from) 1167122394Sharti{ 1168122394Sharti to->var = from->var; 1169122394Sharti to->syntax = from->syntax; 1170122394Sharti 1171122394Sharti if (from->syntax == SNMP_SYNTAX_OCTETSTRING) { 1172122394Sharti if ((to->v.octetstring.len = from->v.octetstring.len) == 0) 1173122394Sharti to->v.octetstring.octets = NULL; 1174122394Sharti else { 1175122394Sharti to->v.octetstring.octets = malloc(to->v.octetstring.len); 1176122394Sharti if (to->v.octetstring.octets == NULL) 1177122394Sharti return (-1); 1178122394Sharti (void)memcpy(to->v.octetstring.octets, 1179122394Sharti from->v.octetstring.octets, to->v.octetstring.len); 1180122394Sharti } 1181122394Sharti } else 1182122394Sharti to->v = from->v; 1183122394Sharti return (0); 1184122394Sharti} 1185122394Sharti 1186122394Shartivoid 1187216594Ssyrinxsnmp_pdu_init_secparams(struct snmp_pdu *pdu) 1188216294Ssyrinx{ 1189216294Ssyrinx int32_t rval; 1190216294Ssyrinx 1191216594Ssyrinx if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH) 1192216294Ssyrinx pdu->flags |= SNMP_MSG_AUTH_FLAG; 1193216294Ssyrinx 1194216594Ssyrinx switch (pdu->user.priv_proto) { 1195216294Ssyrinx case SNMP_PRIV_DES: 1196216594Ssyrinx memcpy(pdu->msg_salt, &pdu->engine.engine_boots, 1197216594Ssyrinx sizeof(pdu->engine.engine_boots)); 1198216294Ssyrinx rval = random(); 1199216594Ssyrinx memcpy(pdu->msg_salt + sizeof(pdu->engine.engine_boots), &rval, 1200216294Ssyrinx sizeof(int32_t)); 1201216294Ssyrinx pdu->flags |= SNMP_MSG_PRIV_FLAG; 1202216294Ssyrinx break; 1203216294Ssyrinx case SNMP_PRIV_AES: 1204216294Ssyrinx rval = random(); 1205216294Ssyrinx memcpy(pdu->msg_salt, &rval, sizeof(int32_t)); 1206216294Ssyrinx rval = random(); 1207216294Ssyrinx memcpy(pdu->msg_salt + sizeof(int32_t), &rval, sizeof(int32_t)); 1208216294Ssyrinx pdu->flags |= SNMP_MSG_PRIV_FLAG; 1209216294Ssyrinx break; 1210216294Ssyrinx default: 1211216294Ssyrinx break; 1212216294Ssyrinx } 1213216294Ssyrinx} 1214216294Ssyrinx 1215216294Ssyrinxvoid 1216122394Shartisnmp_pdu_free(struct snmp_pdu *pdu) 1217122394Sharti{ 1218122394Sharti u_int i; 1219122394Sharti 1220122394Sharti for (i = 0; i < pdu->nbindings; i++) 1221122394Sharti snmp_value_free(&pdu->bindings[i]); 1222312047Sngie pdu->nbindings = 0; 1223122394Sharti} 1224122394Sharti 1225122394Sharti/* 1226122394Sharti * Parse an ASCII SNMP value into the binary form 1227122394Sharti */ 1228122394Shartiint 1229122394Shartisnmp_value_parse(const char *str, enum snmp_syntax syntax, union snmp_values *v) 1230122394Sharti{ 1231122394Sharti char *end; 1232122394Sharti 1233122394Sharti switch (syntax) { 1234122394Sharti 1235122394Sharti case SNMP_SYNTAX_NULL: 1236122394Sharti case SNMP_SYNTAX_NOSUCHOBJECT: 1237122394Sharti case SNMP_SYNTAX_NOSUCHINSTANCE: 1238122394Sharti case SNMP_SYNTAX_ENDOFMIBVIEW: 1239122394Sharti if (*str != '\0') 1240122394Sharti return (-1); 1241122394Sharti return (0); 1242122394Sharti 1243122394Sharti case SNMP_SYNTAX_INTEGER: 1244122394Sharti v->integer = strtoll(str, &end, 0); 1245122394Sharti if (*end != '\0') 1246122394Sharti return (-1); 1247122394Sharti return (0); 1248122394Sharti 1249122394Sharti case SNMP_SYNTAX_OCTETSTRING: 1250122394Sharti { 1251122394Sharti u_long len; /* actual length of string */ 1252122394Sharti u_long alloc; /* allocate length of string */ 1253122394Sharti u_char *octs; /* actual octets */ 1254122394Sharti u_long oct; /* actual octet */ 1255122394Sharti u_char *nocts; /* to avoid memory leak */ 1256122394Sharti u_char c; /* actual character */ 1257122394Sharti 1258122394Sharti# define STUFFC(C) \ 1259122394Sharti if (alloc == len) { \ 1260122394Sharti alloc += 100; \ 1261122394Sharti if ((nocts = realloc(octs, alloc)) == NULL) { \ 1262122394Sharti free(octs); \ 1263122394Sharti return (-1); \ 1264122394Sharti } \ 1265122394Sharti octs = nocts; \ 1266122394Sharti } \ 1267122394Sharti octs[len++] = (C); 1268122394Sharti 1269122394Sharti len = alloc = 0; 1270122394Sharti octs = NULL; 1271122394Sharti 1272122394Sharti if (*str == '"') { 1273122394Sharti str++; 1274122394Sharti while((c = *str++) != '\0') { 1275122394Sharti if (c == '"') { 1276122394Sharti if (*str != '\0') { 1277122394Sharti free(octs); 1278122394Sharti return (-1); 1279122394Sharti } 1280122394Sharti break; 1281122394Sharti } 1282122394Sharti if (c == '\\') { 1283122394Sharti switch (c = *str++) { 1284122394Sharti 1285122394Sharti case '\\': 1286122394Sharti break; 1287122394Sharti case 'a': 1288122394Sharti c = '\a'; 1289122394Sharti break; 1290122394Sharti case 'b': 1291122394Sharti c = '\b'; 1292122394Sharti break; 1293122394Sharti case 'f': 1294122394Sharti c = '\f'; 1295122394Sharti break; 1296122394Sharti case 'n': 1297122394Sharti c = '\n'; 1298122394Sharti break; 1299122394Sharti case 'r': 1300122394Sharti c = '\r'; 1301122394Sharti break; 1302122394Sharti case 't': 1303122394Sharti c = '\t'; 1304122394Sharti break; 1305122394Sharti case 'v': 1306122394Sharti c = '\v'; 1307122394Sharti break; 1308122394Sharti case 'x': 1309122394Sharti c = 0; 1310122394Sharti if (!isxdigit(*str)) 1311122394Sharti break; 1312122394Sharti if (isdigit(*str)) 1313122394Sharti c = *str++ - '0'; 1314122394Sharti else if (isupper(*str)) 1315122394Sharti c = *str++ - 'A' + 10; 1316122394Sharti else 1317122394Sharti c = *str++ - 'a' + 10; 1318122394Sharti if (!isxdigit(*str)) 1319122394Sharti break; 1320122394Sharti if (isdigit(*str)) 1321122394Sharti c += *str++ - '0'; 1322122394Sharti else if (isupper(*str)) 1323122394Sharti c += *str++ - 'A' + 10; 1324122394Sharti else 1325122394Sharti c += *str++ - 'a' + 10; 1326122394Sharti break; 1327122394Sharti case '0': case '1': case '2': 1328122394Sharti case '3': case '4': case '5': 1329122394Sharti case '6': case '7': 1330122394Sharti c = *str++ - '0'; 1331122394Sharti if (*str < '0' || *str > '7') 1332122394Sharti break; 1333122394Sharti c = *str++ - '0'; 1334122394Sharti if (*str < '0' || *str > '7') 1335122394Sharti break; 1336122394Sharti c = *str++ - '0'; 1337122394Sharti break; 1338122394Sharti default: 1339122394Sharti break; 1340122394Sharti } 1341122394Sharti } 1342122394Sharti STUFFC(c); 1343122394Sharti } 1344122394Sharti } else { 1345122394Sharti while (*str != '\0') { 1346122394Sharti oct = strtoul(str, &end, 16); 1347122394Sharti str = end; 1348122394Sharti if (oct > 0xff) { 1349122394Sharti free(octs); 1350122394Sharti return (-1); 1351122394Sharti } 1352122394Sharti STUFFC(oct); 1353122394Sharti if (*str == ':') 1354122394Sharti str++; 1355122394Sharti else if(*str != '\0') { 1356122394Sharti free(octs); 1357122394Sharti return (-1); 1358122394Sharti } 1359122394Sharti } 1360122394Sharti } 1361122394Sharti v->octetstring.octets = octs; 1362122394Sharti v->octetstring.len = len; 1363122394Sharti return (0); 1364122394Sharti# undef STUFFC 1365122394Sharti } 1366122394Sharti 1367122394Sharti case SNMP_SYNTAX_OID: 1368122394Sharti { 1369122394Sharti u_long subid; 1370122394Sharti 1371122394Sharti v->oid.len = 0; 1372122394Sharti 1373122394Sharti for (;;) { 1374122394Sharti if (v->oid.len == ASN_MAXOIDLEN) 1375122394Sharti return (-1); 1376122394Sharti subid = strtoul(str, &end, 10); 1377122394Sharti str = end; 1378122394Sharti if (subid > ASN_MAXID) 1379122394Sharti return (-1); 1380122394Sharti v->oid.subs[v->oid.len++] = (asn_subid_t)subid; 1381122394Sharti if (*str == '\0') 1382122394Sharti break; 1383122394Sharti if (*str != '.') 1384122394Sharti return (-1); 1385122394Sharti str++; 1386122394Sharti } 1387122394Sharti return (0); 1388122394Sharti } 1389122394Sharti 1390122394Sharti case SNMP_SYNTAX_IPADDRESS: 1391122394Sharti { 1392122394Sharti struct hostent *he; 1393122394Sharti 1394311603Sngie if (inet_pton(AF_INET, str, &v->ipaddress) == 1) 1395122394Sharti return (0); 1396311603Sngie if ((he = gethostbyname2(str, AF_INET)) == NULL) 1397122394Sharti return (-1); 1398122394Sharti if (he->h_addrtype != AF_INET) 1399122394Sharti return (-1); 1400122394Sharti 1401311603Sngie memcpy(v->ipaddress, he->h_addr, sizeof(v->ipaddress)); 1402311603Sngie 1403122394Sharti return (0); 1404122394Sharti } 1405122394Sharti 1406122394Sharti case SNMP_SYNTAX_COUNTER: 1407122394Sharti case SNMP_SYNTAX_GAUGE: 1408122394Sharti case SNMP_SYNTAX_TIMETICKS: 1409122394Sharti { 1410133211Sharti uint64_t sub; 1411122394Sharti 1412122394Sharti sub = strtoull(str, &end, 0); 1413122394Sharti if (*end != '\0' || sub > 0xffffffff) 1414122394Sharti return (-1); 1415133211Sharti v->uint32 = (uint32_t)sub; 1416122394Sharti return (0); 1417122394Sharti } 1418122394Sharti 1419122394Sharti case SNMP_SYNTAX_COUNTER64: 1420122394Sharti v->counter64 = strtoull(str, &end, 0); 1421122394Sharti if (*end != '\0') 1422122394Sharti return (-1); 1423122394Sharti return (0); 1424122394Sharti } 1425122394Sharti abort(); 1426122394Sharti} 1427122394Sharti 1428122394Shartistatic void 1429122394Shartisnmp_error_func(const char *fmt, ...) 1430122394Sharti{ 1431122394Sharti va_list ap; 1432122394Sharti 1433122394Sharti va_start(ap, fmt); 1434122394Sharti fprintf(stderr, "SNMP: "); 1435122394Sharti vfprintf(stderr, fmt, ap); 1436122394Sharti fprintf(stderr, "\n"); 1437122394Sharti va_end(ap); 1438122394Sharti} 1439122394Sharti 1440122394Shartistatic void 1441122394Shartisnmp_printf_func(const char *fmt, ...) 1442122394Sharti{ 1443122394Sharti va_list ap; 1444122394Sharti 1445122394Sharti va_start(ap, fmt); 1446122394Sharti vfprintf(stderr, fmt, ap); 1447122394Sharti va_end(ap); 1448122394Sharti} 1449