1 /* 2 * Copyright (c) 2001-2003 3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4 * All rights reserved. 5 * 6 * Author: Harti Brandt <harti@freebsd.org> 7 * 8 * Copyright (c) 2010 The FreeBSD Foundation 9 * All rights reserved. 10 * 11 * Portions of this software were developed by Shteryana Sotirova Shopova 12 * under sponsorship from the FreeBSD Foundation. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 23 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * $Begemot: bsnmp/lib/snmp.c,v 1.40 2005/10/04 14:32:42 brandt_h Exp $ 36 * 37 * SNMP 38 */ 39 #include <sys/types.h> 40 #include <sys/socket.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <stddef.h> 44 #include <stdarg.h> 45 #ifdef HAVE_STDINT_H 46 #include <stdint.h> 47 #elif defined(HAVE_INTTYPES_H) 48 #include <inttypes.h> 49 #endif 50 #include <string.h> 51 #include <ctype.h> 52 #include <netdb.h> 53 #include <errno.h> 54 55 #include "asn1.h" 56 #include "snmp.h" 57 #include "snmppriv.h" 58 59 static void snmp_error_func(const char *, ...); 60 static void snmp_printf_func(const char *, ...); 61 62 void (*snmp_error)(const char *, ...) = snmp_error_func; 63 void (*snmp_printf)(const char *, ...) = snmp_printf_func; 64 65 /* 66 * Get the next variable binding from the list. 67 * ASN errors on the sequence or the OID are always fatal. 68 */ 69 static enum asn_err 70 get_var_binding(struct asn_buf *b, struct snmp_value *binding) 71 { 72 u_char type; 73 asn_len_t len, trailer; 74 enum asn_err err; 75 76 if (asn_get_sequence(b, &len) != ASN_ERR_OK) { 77 snmp_error("cannot parse varbind header"); 78 return (ASN_ERR_FAILED); 79 } 80 81 /* temporary truncate the length so that the parser does not 82 * eat up bytes behind the sequence in the case the encoding is 83 * wrong of inner elements. */ 84 trailer = b->asn_len - len; 85 b->asn_len = len; 86 87 if (asn_get_objid(b, &binding->var) != ASN_ERR_OK) { 88 snmp_error("cannot parse binding objid"); 89 return (ASN_ERR_FAILED); 90 } 91 if (asn_get_header(b, &type, &len) != ASN_ERR_OK) { 92 snmp_error("cannot parse binding value header"); 93 return (ASN_ERR_FAILED); 94 } 95 96 switch (type) { 97 98 case ASN_TYPE_NULL: 99 binding->syntax = SNMP_SYNTAX_NULL; 100 err = asn_get_null_raw(b, len); 101 break; 102 103 case ASN_TYPE_INTEGER: 104 binding->syntax = SNMP_SYNTAX_INTEGER; 105 err = asn_get_integer_raw(b, len, &binding->v.integer); 106 break; 107 108 case ASN_TYPE_OCTETSTRING: 109 binding->syntax = SNMP_SYNTAX_OCTETSTRING; 110 binding->v.octetstring.octets = malloc(len); 111 if (binding->v.octetstring.octets == NULL) { 112 snmp_error("%s", strerror(errno)); 113 return (ASN_ERR_FAILED); 114 } 115 binding->v.octetstring.len = len; 116 err = asn_get_octetstring_raw(b, len, 117 binding->v.octetstring.octets, 118 &binding->v.octetstring.len); 119 if (ASN_ERR_STOPPED(err)) { 120 free(binding->v.octetstring.octets); 121 binding->v.octetstring.octets = NULL; 122 } 123 break; 124 125 case ASN_TYPE_OBJID: 126 binding->syntax = SNMP_SYNTAX_OID; 127 err = asn_get_objid_raw(b, len, &binding->v.oid); 128 break; 129 130 case ASN_CLASS_APPLICATION|ASN_APP_IPADDRESS: 131 binding->syntax = SNMP_SYNTAX_IPADDRESS; 132 err = asn_get_ipaddress_raw(b, len, binding->v.ipaddress); 133 break; 134 135 case ASN_CLASS_APPLICATION|ASN_APP_TIMETICKS: 136 binding->syntax = SNMP_SYNTAX_TIMETICKS; 137 err = asn_get_uint32_raw(b, len, &binding->v.uint32); 138 break; 139 140 case ASN_CLASS_APPLICATION|ASN_APP_COUNTER: 141 binding->syntax = SNMP_SYNTAX_COUNTER; 142 err = asn_get_uint32_raw(b, len, &binding->v.uint32); 143 break; 144 145 case ASN_CLASS_APPLICATION|ASN_APP_GAUGE: 146 binding->syntax = SNMP_SYNTAX_GAUGE; 147 err = asn_get_uint32_raw(b, len, &binding->v.uint32); 148 break; 149 150 case ASN_CLASS_APPLICATION|ASN_APP_COUNTER64: 151 binding->syntax = SNMP_SYNTAX_COUNTER64; 152 err = asn_get_counter64_raw(b, len, &binding->v.counter64); 153 break; 154 155 case ASN_CLASS_CONTEXT | ASN_EXCEPT_NOSUCHOBJECT: 156 binding->syntax = SNMP_SYNTAX_NOSUCHOBJECT; 157 err = asn_get_null_raw(b, len); 158 break; 159 160 case ASN_CLASS_CONTEXT | ASN_EXCEPT_NOSUCHINSTANCE: 161 binding->syntax = SNMP_SYNTAX_NOSUCHINSTANCE; 162 err = asn_get_null_raw(b, len); 163 break; 164 165 case ASN_CLASS_CONTEXT | ASN_EXCEPT_ENDOFMIBVIEW: 166 binding->syntax = SNMP_SYNTAX_ENDOFMIBVIEW; 167 err = asn_get_null_raw(b, len); 168 break; 169 170 default: 171 if ((err = asn_skip(b, len)) == ASN_ERR_OK) 172 err = ASN_ERR_TAG; 173 snmp_error("bad binding value type 0x%x", type); 174 break; 175 } 176 177 if (ASN_ERR_STOPPED(err)) { 178 snmp_error("cannot parse binding value"); 179 return (err); 180 } 181 182 if (b->asn_len != 0) 183 snmp_error("ignoring junk at end of binding"); 184 185 b->asn_len = trailer; 186 187 return (err); 188 } 189 190 /* 191 * Parse the different PDUs contents. Any ASN error in the outer components 192 * are fatal. Only errors in variable values may be tolerated. If all 193 * components can be parsed it returns either ASN_ERR_OK or the first 194 * error that was found. 195 */ 196 enum asn_err 197 snmp_parse_pdus_hdr(struct asn_buf *b, struct snmp_pdu *pdu, asn_len_t *lenp) 198 { 199 if (pdu->type == SNMP_PDU_TRAP) { 200 if (asn_get_objid(b, &pdu->enterprise) != ASN_ERR_OK) { 201 snmp_error("cannot parse trap enterprise"); 202 return (ASN_ERR_FAILED); 203 } 204 if (asn_get_ipaddress(b, pdu->agent_addr) != ASN_ERR_OK) { 205 snmp_error("cannot parse trap agent address"); 206 return (ASN_ERR_FAILED); 207 } 208 if (asn_get_integer(b, &pdu->generic_trap) != ASN_ERR_OK) { 209 snmp_error("cannot parse 'generic-trap'"); 210 return (ASN_ERR_FAILED); 211 } 212 if (asn_get_integer(b, &pdu->specific_trap) != ASN_ERR_OK) { 213 snmp_error("cannot parse 'specific-trap'"); 214 return (ASN_ERR_FAILED); 215 } 216 if (asn_get_timeticks(b, &pdu->time_stamp) != ASN_ERR_OK) { 217 snmp_error("cannot parse trap 'time-stamp'"); 218 return (ASN_ERR_FAILED); 219 } 220 } else { 221 if (asn_get_integer(b, &pdu->request_id) != ASN_ERR_OK) { 222 snmp_error("cannot parse 'request-id'"); 223 return (ASN_ERR_FAILED); 224 } 225 if (asn_get_integer(b, &pdu->error_status) != ASN_ERR_OK) { 226 snmp_error("cannot parse 'error_status'"); 227 return (ASN_ERR_FAILED); 228 } 229 if (asn_get_integer(b, &pdu->error_index) != ASN_ERR_OK) { 230 snmp_error("cannot parse 'error_index'"); 231 return (ASN_ERR_FAILED); 232 } 233 } 234 235 if (asn_get_sequence(b, lenp) != ASN_ERR_OK) { 236 snmp_error("cannot get varlist header"); 237 return (ASN_ERR_FAILED); 238 } 239 240 return (ASN_ERR_OK); 241 } 242 243 static enum asn_err 244 parse_pdus(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip) 245 { 246 asn_len_t len, trailer; 247 struct snmp_value *v; 248 enum asn_err err, err1; 249 250 err = snmp_parse_pdus_hdr(b, pdu, &len); 251 if (ASN_ERR_STOPPED(err)) 252 return (err); 253 254 trailer = b->asn_len - len; 255 256 v = pdu->bindings; 257 err = ASN_ERR_OK; 258 while (b->asn_len != 0) { 259 if (pdu->nbindings == SNMP_MAX_BINDINGS) { 260 snmp_error("too many bindings (> %u) in PDU", 261 SNMP_MAX_BINDINGS); 262 return (ASN_ERR_FAILED); 263 } 264 err1 = get_var_binding(b, v); 265 if (ASN_ERR_STOPPED(err1)) 266 return (ASN_ERR_FAILED); 267 if (err1 != ASN_ERR_OK && err == ASN_ERR_OK) { 268 err = err1; 269 *ip = pdu->nbindings + 1; 270 } 271 pdu->nbindings++; 272 v++; 273 } 274 275 b->asn_len = trailer; 276 277 return (err); 278 } 279 280 281 static enum asn_err 282 parse_secparams(struct asn_buf *b, struct snmp_pdu *pdu) 283 { 284 asn_len_t octs_len; 285 u_char buf[256]; /* XXX: calc max possible size here */ 286 struct asn_buf tb; 287 288 memset(buf, 0, 256); 289 tb.asn_ptr = buf; 290 tb.asn_len = 256; 291 292 if (asn_get_octetstring(b, buf, &tb.asn_len) != ASN_ERR_OK) { 293 snmp_error("cannot parse usm header"); 294 return (ASN_ERR_FAILED); 295 } 296 297 if (asn_get_sequence(&tb, &octs_len) != ASN_ERR_OK) { 298 snmp_error("cannot decode usm header"); 299 return (ASN_ERR_FAILED); 300 } 301 302 octs_len = SNMP_ENGINE_ID_SIZ; 303 if (asn_get_octetstring(&tb, (u_char *)&pdu->engine.engine_id, 304 &octs_len) != ASN_ERR_OK) { 305 snmp_error("cannot decode msg engine id"); 306 return (ASN_ERR_FAILED); 307 } 308 pdu->engine.engine_len = octs_len; 309 310 if (asn_get_integer(&tb, &pdu->engine.engine_boots) != ASN_ERR_OK) { 311 snmp_error("cannot decode msg engine boots"); 312 return (ASN_ERR_FAILED); 313 } 314 315 if (asn_get_integer(&tb, &pdu->engine.engine_time) != ASN_ERR_OK) { 316 snmp_error("cannot decode msg engine time"); 317 return (ASN_ERR_FAILED); 318 } 319 320 octs_len = SNMP_ADM_STR32_SIZ - 1; 321 if (asn_get_octetstring(&tb, (u_char *)&pdu->user.sec_name, &octs_len) 322 != ASN_ERR_OK) { 323 snmp_error("cannot decode msg user name"); 324 return (ASN_ERR_FAILED); 325 } 326 pdu->user.sec_name[octs_len] = '\0'; 327 328 octs_len = sizeof(pdu->msg_digest); 329 if (asn_get_octetstring(&tb, (u_char *)&pdu->msg_digest, &octs_len) != 330 ASN_ERR_OK || ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0 && 331 octs_len != sizeof(pdu->msg_digest))) { 332 snmp_error("cannot decode msg authentication param"); 333 return (ASN_ERR_FAILED); 334 } 335 336 octs_len = sizeof(pdu->msg_salt); 337 if (asn_get_octetstring(&tb, (u_char *)&pdu->msg_salt, &octs_len) != 338 ASN_ERR_OK ||((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0 && 339 octs_len != sizeof(pdu->msg_salt))) { 340 snmp_error("cannot decode msg authentication param"); 341 return (ASN_ERR_FAILED); 342 } 343 344 if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) { 345 pdu->digest_ptr = b->asn_ptr - SNMP_USM_AUTH_SIZE; 346 pdu->digest_ptr -= octs_len + ASN_MAXLENLEN; 347 } 348 349 return (ASN_ERR_OK); 350 } 351 352 static enum snmp_code 353 pdu_encode_secparams(struct asn_buf *b, struct snmp_pdu *pdu) 354 { 355 u_char buf[256], *sptr; 356 struct asn_buf tb; 357 size_t auth_off, moved = 0; 358 359 auth_off = 0; 360 memset(buf, 0, 256); 361 tb.asn_ptr = buf; 362 tb.asn_len = 256; 363 364 if (asn_put_temp_header(&tb, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED), 365 &sptr) != ASN_ERR_OK) 366 return (SNMP_CODE_FAILED); 367 368 if (asn_put_octetstring(&tb, (u_char *)pdu->engine.engine_id, 369 pdu->engine.engine_len) != ASN_ERR_OK) 370 return (SNMP_CODE_FAILED); 371 372 if (asn_put_integer(&tb, pdu->engine.engine_boots) != ASN_ERR_OK) 373 return (SNMP_CODE_FAILED); 374 375 if (asn_put_integer(&tb, pdu->engine.engine_time) != ASN_ERR_OK) 376 return (SNMP_CODE_FAILED); 377 378 if (asn_put_octetstring(&tb, (u_char *)pdu->user.sec_name, 379 strlen(pdu->user.sec_name)) != ASN_ERR_OK) 380 return (SNMP_CODE_FAILED); 381 382 if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) { 383 auth_off = sizeof(buf) - tb.asn_len + ASN_MAXLENLEN; 384 if (asn_put_octetstring(&tb, (u_char *)pdu->msg_digest, 385 sizeof(pdu->msg_digest)) != ASN_ERR_OK) 386 return (SNMP_CODE_FAILED); 387 } else { 388 if (asn_put_octetstring(&tb, (u_char *)pdu->msg_digest, 0) 389 != ASN_ERR_OK) 390 return (SNMP_CODE_FAILED); 391 } 392 393 if ((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0) { 394 if (asn_put_octetstring(&tb, (u_char *)pdu->msg_salt, 395 sizeof(pdu->msg_salt)) != ASN_ERR_OK) 396 return (SNMP_CODE_FAILED); 397 } else { 398 if (asn_put_octetstring(&tb, (u_char *)pdu->msg_salt, 0) 399 != ASN_ERR_OK) 400 return (SNMP_CODE_FAILED); 401 } 402 403 if (asn_commit_header(&tb, sptr, &moved) != ASN_ERR_OK) 404 return (SNMP_CODE_FAILED); 405 406 if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) 407 pdu->digest_ptr = b->asn_ptr + auth_off - moved; 408 409 if (asn_put_octetstring(b, buf, sizeof(buf) - tb.asn_len) != ASN_ERR_OK) 410 return (SNMP_CODE_FAILED); 411 pdu->digest_ptr += ASN_MAXLENLEN; 412 413 if ((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0 && asn_put_temp_header(b, 414 ASN_TYPE_OCTETSTRING, &pdu->encrypted_ptr) != ASN_ERR_OK) 415 return (SNMP_CODE_FAILED); 416 417 return (SNMP_CODE_OK); 418 } 419 420 /* 421 * Decode the PDU except for the variable bindings itself. 422 * If decoding fails because of a bad binding, but the rest can be 423 * decoded, ip points to the index of the failed variable (errors 424 * OORANGE, BADLEN or BADVERS). 425 */ 426 enum snmp_code 427 snmp_pdu_decode(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip) 428 { 429 enum snmp_code code; 430 431 if ((code = snmp_pdu_decode_header(b, pdu)) != SNMP_CODE_OK) 432 return (code); 433 434 if (pdu->version == SNMP_V3) { 435 if (pdu->security_model != SNMP_SECMODEL_USM) 436 return (SNMP_CODE_FAILED); 437 if ((code = snmp_pdu_decode_secmode(b, pdu)) != SNMP_CODE_OK) 438 return (code); 439 } 440 441 code = snmp_pdu_decode_scoped(b, pdu, ip); 442 443 switch (code) { 444 case SNMP_CODE_FAILED: 445 snmp_pdu_free(pdu); 446 break; 447 448 case SNMP_CODE_BADENC: 449 if (pdu->version == SNMP_Verr) 450 return (SNMP_CODE_BADVERS); 451 452 default: 453 break; 454 } 455 456 return (code); 457 } 458 459 enum snmp_code 460 snmp_pdu_decode_header(struct asn_buf *b, struct snmp_pdu *pdu) 461 { 462 int32_t version; 463 u_int octs_len; 464 asn_len_t len; 465 466 pdu->outer_ptr = b->asn_ptr; 467 pdu->outer_len = b->asn_len; 468 469 if (asn_get_sequence(b, &len) != ASN_ERR_OK) { 470 snmp_error("cannot decode pdu header"); 471 return (SNMP_CODE_FAILED); 472 } 473 if (b->asn_len < len) { 474 snmp_error("outer sequence value too short"); 475 return (SNMP_CODE_FAILED); 476 } 477 if (b->asn_len != len) { 478 snmp_error("ignoring trailing junk in message"); 479 b->asn_len = len; 480 } 481 482 if (asn_get_integer(b, &version) != ASN_ERR_OK) { 483 snmp_error("cannot decode version"); 484 return (SNMP_CODE_FAILED); 485 } 486 487 if (version == 0) 488 pdu->version = SNMP_V1; 489 else if (version == 1) 490 pdu->version = SNMP_V2c; 491 else if (version == 3) 492 pdu->version = SNMP_V3; 493 else { 494 pdu->version = SNMP_Verr; 495 snmp_error("unsupported SNMP version"); 496 return (SNMP_CODE_BADENC); 497 } 498 499 if (pdu->version == SNMP_V3) { 500 if (asn_get_sequence(b, &len) != ASN_ERR_OK) { 501 snmp_error("cannot decode pdu global data header"); 502 return (SNMP_CODE_FAILED); 503 } 504 505 if (asn_get_integer(b, &pdu->identifier) != ASN_ERR_OK) { 506 snmp_error("cannot decode msg indetifier"); 507 return (SNMP_CODE_FAILED); 508 } 509 510 if (asn_get_integer(b, &pdu->engine.max_msg_size) 511 != ASN_ERR_OK) { 512 snmp_error("cannot decode msg size"); 513 return (SNMP_CODE_FAILED); 514 } 515 516 octs_len = 1; 517 if (asn_get_octetstring(b, (u_char *)&pdu->flags, 518 &octs_len) != ASN_ERR_OK) { 519 snmp_error("cannot decode msg flags"); 520 return (SNMP_CODE_FAILED); 521 } 522 523 if (asn_get_integer(b, &pdu->security_model) != ASN_ERR_OK) { 524 snmp_error("cannot decode msg size"); 525 return (SNMP_CODE_FAILED); 526 } 527 528 if (pdu->security_model != SNMP_SECMODEL_USM) 529 return (SNMP_CODE_FAILED); 530 531 if (parse_secparams(b, pdu) != ASN_ERR_OK) 532 return (SNMP_CODE_FAILED); 533 } else { 534 octs_len = SNMP_COMMUNITY_MAXLEN; 535 if (asn_get_octetstring(b, (u_char *)pdu->community, 536 &octs_len) != ASN_ERR_OK) { 537 snmp_error("cannot decode community"); 538 return (SNMP_CODE_FAILED); 539 } 540 pdu->community[octs_len] = '\0'; 541 } 542 543 return (SNMP_CODE_OK); 544 } 545 546 enum snmp_code 547 snmp_pdu_decode_scoped(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip) 548 { 549 u_char type; 550 asn_len_t len, trailer; 551 enum asn_err err; 552 553 if (pdu->version == SNMP_V3) { 554 if (asn_get_sequence(b, &len) != ASN_ERR_OK) { 555 snmp_error("cannot decode scoped pdu header"); 556 return (SNMP_CODE_FAILED); 557 } 558 559 len = SNMP_ENGINE_ID_SIZ; 560 if (asn_get_octetstring(b, (u_char *)&pdu->context_engine, 561 &len) != ASN_ERR_OK) { 562 snmp_error("cannot decode msg context engine"); 563 return (SNMP_CODE_FAILED); 564 } 565 pdu->context_engine_len = len; 566 567 len = SNMP_CONTEXT_NAME_SIZ; 568 if (asn_get_octetstring(b, (u_char *)&pdu->context_name, 569 &len) != ASN_ERR_OK) { 570 snmp_error("cannot decode msg context name"); 571 return (SNMP_CODE_FAILED); 572 } 573 pdu->context_name[len] = '\0'; 574 } 575 576 if (asn_get_header(b, &type, &len) != ASN_ERR_OK) { 577 snmp_error("cannot get pdu header"); 578 return (SNMP_CODE_FAILED); 579 } 580 if ((type & ~ASN_TYPE_MASK) != 581 (ASN_TYPE_CONSTRUCTED | ASN_CLASS_CONTEXT)) { 582 snmp_error("bad pdu header tag"); 583 return (SNMP_CODE_FAILED); 584 } 585 pdu->type = type & ASN_TYPE_MASK; 586 587 switch (pdu->type) { 588 589 case SNMP_PDU_GET: 590 case SNMP_PDU_GETNEXT: 591 case SNMP_PDU_RESPONSE: 592 case SNMP_PDU_SET: 593 break; 594 595 case SNMP_PDU_TRAP: 596 if (pdu->version != SNMP_V1) { 597 snmp_error("bad pdu type %u", pdu->type); 598 return (SNMP_CODE_FAILED); 599 } 600 break; 601 602 case SNMP_PDU_GETBULK: 603 case SNMP_PDU_INFORM: 604 case SNMP_PDU_TRAP2: 605 case SNMP_PDU_REPORT: 606 if (pdu->version == SNMP_V1) { 607 snmp_error("bad pdu type %u", pdu->type); 608 return (SNMP_CODE_FAILED); 609 } 610 break; 611 612 default: 613 snmp_error("bad pdu type %u", pdu->type); 614 return (SNMP_CODE_FAILED); 615 } 616 617 trailer = b->asn_len - len; 618 b->asn_len = len; 619 620 err = parse_pdus(b, pdu, ip); 621 if (ASN_ERR_STOPPED(err)) 622 return (SNMP_CODE_FAILED); 623 624 if (b->asn_len != 0) 625 snmp_error("ignoring trailing junk after pdu"); 626 627 b->asn_len = trailer; 628 629 return (SNMP_CODE_OK); 630 } 631 632 enum snmp_code 633 snmp_pdu_decode_secmode(struct asn_buf *b, struct snmp_pdu *pdu) 634 { 635 u_char type; 636 enum snmp_code code; 637 uint8_t digest[SNMP_USM_AUTH_SIZE]; 638 639 if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH && 640 (pdu->flags & SNMP_MSG_AUTH_FLAG) == 0) 641 return (SNMP_CODE_BADSECLEVEL); 642 643 if ((code = snmp_pdu_calc_digest(pdu, digest)) != 644 SNMP_CODE_OK) 645 return (SNMP_CODE_FAILED); 646 647 if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH && 648 memcmp(digest, pdu->msg_digest, sizeof(pdu->msg_digest)) != 0) 649 return (SNMP_CODE_BADDIGEST); 650 651 if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV && (asn_get_header(b, &type, 652 &pdu->scoped_len) != ASN_ERR_OK || type != ASN_TYPE_OCTETSTRING)) { 653 snmp_error("cannot decode encrypted pdu"); 654 return (SNMP_CODE_FAILED); 655 } 656 pdu->scoped_ptr = b->asn_ptr; 657 658 if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV && 659 (pdu->flags & SNMP_MSG_PRIV_FLAG) == 0) 660 return (SNMP_CODE_BADSECLEVEL); 661 662 if ((code = snmp_pdu_decrypt(pdu)) != SNMP_CODE_OK) 663 return (SNMP_CODE_FAILED); 664 665 return (code); 666 } 667 668 /* 669 * Check whether what we have is the complete PDU by snooping at the 670 * enclosing structure header. This returns: 671 * -1 if there are ASN.1 errors 672 * 0 if we need more data 673 * > 0 the length of this PDU 674 */ 675 int 676 snmp_pdu_snoop(const struct asn_buf *b0) 677 { 678 u_int length; 679 asn_len_t len; 680 struct asn_buf b = *b0; 681 682 /* <0x10|0x20> <len> <data...> */ 683 684 if (b.asn_len == 0) 685 return (0); 686 if (b.asn_cptr[0] != (ASN_TYPE_SEQUENCE | ASN_TYPE_CONSTRUCTED)) { 687 asn_error(&b, "bad sequence type %u", b.asn_cptr[0]); 688 return (-1); 689 } 690 b.asn_len--; 691 b.asn_cptr++; 692 693 if (b.asn_len == 0) 694 return (0); 695 696 if (*b.asn_cptr & 0x80) { 697 /* long length */ 698 length = *b.asn_cptr++ & 0x7f; 699 b.asn_len--; 700 if (length == 0) { 701 asn_error(&b, "indefinite length not supported"); 702 return (-1); 703 } 704 if (length > ASN_MAXLENLEN) { 705 asn_error(&b, "long length too long (%u)", length); 706 return (-1); 707 } 708 if (length > b.asn_len) 709 return (0); 710 len = 0; 711 while (length--) { 712 len = (len << 8) | *b.asn_cptr++; 713 b.asn_len--; 714 } 715 } else { 716 len = *b.asn_cptr++; 717 b.asn_len--; 718 } 719 720 if (len > b.asn_len) 721 return (0); 722 723 return (len + b.asn_cptr - b0->asn_cptr); 724 } 725 726 /* 727 * Encode the SNMP PDU without the variable bindings field. 728 * We do this the rather uneffective way by 729 * moving things around and assuming that the length field will never 730 * use more than 2 bytes. 731 * We need a number of pointers to apply the fixes afterwards. 732 */ 733 enum snmp_code 734 snmp_pdu_encode_header(struct asn_buf *b, struct snmp_pdu *pdu) 735 { 736 enum asn_err err; 737 u_char *v3_hdr_ptr; 738 739 if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED), 740 &pdu->outer_ptr) != ASN_ERR_OK) 741 return (SNMP_CODE_FAILED); 742 743 if (pdu->version == SNMP_V1) 744 err = asn_put_integer(b, 0); 745 else if (pdu->version == SNMP_V2c) 746 err = asn_put_integer(b, 1); 747 else if (pdu->version == SNMP_V3) 748 err = asn_put_integer(b, 3); 749 else 750 return (SNMP_CODE_BADVERS); 751 if (err != ASN_ERR_OK) 752 return (SNMP_CODE_FAILED); 753 754 if (pdu->version == SNMP_V3) { 755 if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE | 756 ASN_TYPE_CONSTRUCTED), &v3_hdr_ptr) != ASN_ERR_OK) 757 return (SNMP_CODE_FAILED); 758 759 if (asn_put_integer(b, pdu->identifier) != ASN_ERR_OK) 760 return (SNMP_CODE_FAILED); 761 762 if (asn_put_integer(b, pdu->engine.max_msg_size) != ASN_ERR_OK) 763 return (SNMP_CODE_FAILED); 764 765 if (pdu->type != SNMP_PDU_RESPONSE && 766 pdu->type != SNMP_PDU_TRAP && 767 pdu->type != SNMP_PDU_TRAP2 && 768 pdu->type != SNMP_PDU_REPORT) 769 pdu->flags |= SNMP_MSG_REPORT_FLAG; 770 771 if (asn_put_octetstring(b, (u_char *)&pdu->flags, 1) 772 != ASN_ERR_OK) 773 return (SNMP_CODE_FAILED); 774 775 if (asn_put_integer(b, pdu->security_model) != ASN_ERR_OK) 776 return (SNMP_CODE_FAILED); 777 778 if (asn_commit_header(b, v3_hdr_ptr, NULL) != ASN_ERR_OK) 779 return (SNMP_CODE_FAILED); 780 781 if (pdu->security_model != SNMP_SECMODEL_USM) 782 return (SNMP_CODE_FAILED); 783 784 if (pdu_encode_secparams(b, pdu) != SNMP_CODE_OK) 785 return (SNMP_CODE_FAILED); 786 787 /* View-based Access Conntrol information */ 788 if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE | 789 ASN_TYPE_CONSTRUCTED), &pdu->scoped_ptr) != ASN_ERR_OK) 790 return (SNMP_CODE_FAILED); 791 792 if (asn_put_octetstring(b, (u_char *)pdu->context_engine, 793 pdu->context_engine_len) != ASN_ERR_OK) 794 return (SNMP_CODE_FAILED); 795 796 if (asn_put_octetstring(b, (u_char *)pdu->context_name, 797 strlen(pdu->context_name)) != ASN_ERR_OK) 798 return (SNMP_CODE_FAILED); 799 } else { 800 if (asn_put_octetstring(b, (u_char *)pdu->community, 801 strlen(pdu->community)) != ASN_ERR_OK) 802 return (SNMP_CODE_FAILED); 803 } 804 805 if (asn_put_temp_header(b, (ASN_TYPE_CONSTRUCTED | ASN_CLASS_CONTEXT | 806 pdu->type), &pdu->pdu_ptr) != ASN_ERR_OK) 807 return (SNMP_CODE_FAILED); 808 809 if (pdu->type == SNMP_PDU_TRAP) { 810 if (pdu->version != SNMP_V1 || 811 asn_put_objid(b, &pdu->enterprise) != ASN_ERR_OK || 812 asn_put_ipaddress(b, pdu->agent_addr) != ASN_ERR_OK || 813 asn_put_integer(b, pdu->generic_trap) != ASN_ERR_OK || 814 asn_put_integer(b, pdu->specific_trap) != ASN_ERR_OK || 815 asn_put_timeticks(b, pdu->time_stamp) != ASN_ERR_OK) 816 return (SNMP_CODE_FAILED); 817 } else { 818 if (pdu->version == SNMP_V1 && (pdu->type == SNMP_PDU_GETBULK || 819 pdu->type == SNMP_PDU_INFORM || 820 pdu->type == SNMP_PDU_TRAP2 || 821 pdu->type == SNMP_PDU_REPORT)) 822 return (SNMP_CODE_FAILED); 823 824 if (asn_put_integer(b, pdu->request_id) != ASN_ERR_OK || 825 asn_put_integer(b, pdu->error_status) != ASN_ERR_OK || 826 asn_put_integer(b, pdu->error_index) != ASN_ERR_OK) 827 return (SNMP_CODE_FAILED); 828 } 829 830 if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED), 831 &pdu->vars_ptr) != ASN_ERR_OK) 832 return (SNMP_CODE_FAILED); 833 834 return (SNMP_CODE_OK); 835 } 836 837 static enum asn_err 838 snmp_pdu_fix_padd(struct asn_buf *b, struct snmp_pdu *pdu) 839 { 840 asn_len_t padlen; 841 842 if (pdu->user.priv_proto == SNMP_PRIV_DES && pdu->scoped_len % 8 != 0) { 843 padlen = 8 - (pdu->scoped_len % 8); 844 if (asn_pad(b, padlen) != ASN_ERR_OK) 845 return (ASN_ERR_FAILED); 846 pdu->scoped_len += padlen; 847 } 848 849 return (ASN_ERR_OK); 850 } 851 852 enum snmp_code 853 snmp_fix_encoding(struct asn_buf *b, struct snmp_pdu *pdu) 854 { 855 size_t moved = 0; 856 enum snmp_code code; 857 858 if (asn_commit_header(b, pdu->vars_ptr, NULL) != ASN_ERR_OK || 859 asn_commit_header(b, pdu->pdu_ptr, NULL) != ASN_ERR_OK) 860 return (SNMP_CODE_FAILED); 861 862 if (pdu->version == SNMP_V3) { 863 if (asn_commit_header(b, pdu->scoped_ptr, NULL) != ASN_ERR_OK) 864 return (SNMP_CODE_FAILED); 865 866 pdu->scoped_len = b->asn_ptr - pdu->scoped_ptr; 867 if ((code = snmp_pdu_fix_padd(b, pdu))!= ASN_ERR_OK) 868 return (SNMP_CODE_FAILED); 869 870 if (pdu->security_model != SNMP_SECMODEL_USM) 871 return (SNMP_CODE_FAILED); 872 873 if (snmp_pdu_encrypt(pdu) != SNMP_CODE_OK) 874 return (SNMP_CODE_FAILED); 875 876 if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV && 877 asn_commit_header(b, pdu->encrypted_ptr, NULL) != ASN_ERR_OK) 878 return (SNMP_CODE_FAILED); 879 } 880 881 if (asn_commit_header(b, pdu->outer_ptr, &moved) != ASN_ERR_OK) 882 return (SNMP_CODE_FAILED); 883 884 pdu->outer_len = b->asn_ptr - pdu->outer_ptr; 885 pdu->digest_ptr -= moved; 886 887 if (pdu->version == SNMP_V3) { 888 if ((code = snmp_pdu_calc_digest(pdu, pdu->msg_digest)) != 889 SNMP_CODE_OK) 890 return (SNMP_CODE_FAILED); 891 892 if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) 893 memcpy(pdu->digest_ptr, pdu->msg_digest, 894 sizeof(pdu->msg_digest)); 895 } 896 897 return (SNMP_CODE_OK); 898 } 899 900 /* 901 * Encode a binding. Caller must ensure, that the syntax is ok for that version. 902 * Be sure not to cobber b, when something fails. 903 */ 904 enum asn_err 905 snmp_binding_encode(struct asn_buf *b, const struct snmp_value *binding) 906 { 907 u_char *ptr; 908 enum asn_err err; 909 struct asn_buf save = *b; 910 911 if ((err = asn_put_temp_header(b, (ASN_TYPE_SEQUENCE | 912 ASN_TYPE_CONSTRUCTED), &ptr)) != ASN_ERR_OK) { 913 *b = save; 914 return (err); 915 } 916 917 if ((err = asn_put_objid(b, &binding->var)) != ASN_ERR_OK) { 918 *b = save; 919 return (err); 920 } 921 922 switch (binding->syntax) { 923 924 case SNMP_SYNTAX_NULL: 925 err = asn_put_null(b); 926 break; 927 928 case SNMP_SYNTAX_INTEGER: 929 err = asn_put_integer(b, binding->v.integer); 930 break; 931 932 case SNMP_SYNTAX_OCTETSTRING: 933 err = asn_put_octetstring(b, binding->v.octetstring.octets, 934 binding->v.octetstring.len); 935 break; 936 937 case SNMP_SYNTAX_OID: 938 err = asn_put_objid(b, &binding->v.oid); 939 break; 940 941 case SNMP_SYNTAX_IPADDRESS: 942 err = asn_put_ipaddress(b, binding->v.ipaddress); 943 break; 944 945 case SNMP_SYNTAX_TIMETICKS: 946 err = asn_put_uint32(b, ASN_APP_TIMETICKS, binding->v.uint32); 947 break; 948 949 case SNMP_SYNTAX_COUNTER: 950 err = asn_put_uint32(b, ASN_APP_COUNTER, binding->v.uint32); 951 break; 952 953 case SNMP_SYNTAX_GAUGE: 954 err = asn_put_uint32(b, ASN_APP_GAUGE, binding->v.uint32); 955 break; 956 957 case SNMP_SYNTAX_COUNTER64: 958 err = asn_put_counter64(b, binding->v.counter64); 959 break; 960 961 case SNMP_SYNTAX_NOSUCHOBJECT: 962 err = asn_put_exception(b, ASN_EXCEPT_NOSUCHOBJECT); 963 break; 964 965 case SNMP_SYNTAX_NOSUCHINSTANCE: 966 err = asn_put_exception(b, ASN_EXCEPT_NOSUCHINSTANCE); 967 break; 968 969 case SNMP_SYNTAX_ENDOFMIBVIEW: 970 err = asn_put_exception(b, ASN_EXCEPT_ENDOFMIBVIEW); 971 break; 972 } 973 974 if (err != ASN_ERR_OK) { 975 *b = save; 976 return (err); 977 } 978 979 err = asn_commit_header(b, ptr, NULL); 980 if (err != ASN_ERR_OK) { 981 *b = save; 982 return (err); 983 } 984 985 return (ASN_ERR_OK); 986 } 987 988 /* 989 * Encode an PDU. 990 */ 991 enum snmp_code 992 snmp_pdu_encode(struct snmp_pdu *pdu, struct asn_buf *resp_b) 993 { 994 u_int idx; 995 enum snmp_code err; 996 997 if ((err = snmp_pdu_encode_header(resp_b, pdu)) != SNMP_CODE_OK) 998 return (err); 999 for (idx = 0; idx < pdu->nbindings; idx++) 1000 if ((err = snmp_binding_encode(resp_b, &pdu->bindings[idx])) 1001 != ASN_ERR_OK) 1002 return (SNMP_CODE_FAILED); 1003 1004 return (snmp_fix_encoding(resp_b, pdu)); 1005 } 1006 1007 static void 1008 dump_binding(const struct snmp_value *b) 1009 { 1010 u_int i; 1011 char buf[ASN_OIDSTRLEN]; 1012 1013 snmp_printf("%s=", asn_oid2str_r(&b->var, buf)); 1014 switch (b->syntax) { 1015 1016 case SNMP_SYNTAX_NULL: 1017 snmp_printf("NULL"); 1018 break; 1019 1020 case SNMP_SYNTAX_INTEGER: 1021 snmp_printf("INTEGER %d", b->v.integer); 1022 break; 1023 1024 case SNMP_SYNTAX_OCTETSTRING: 1025 snmp_printf("OCTET STRING %lu:", b->v.octetstring.len); 1026 for (i = 0; i < b->v.octetstring.len; i++) 1027 snmp_printf(" %02x", b->v.octetstring.octets[i]); 1028 break; 1029 1030 case SNMP_SYNTAX_OID: 1031 snmp_printf("OID %s", asn_oid2str_r(&b->v.oid, buf)); 1032 break; 1033 1034 case SNMP_SYNTAX_IPADDRESS: 1035 snmp_printf("IPADDRESS %u.%u.%u.%u", b->v.ipaddress[0], 1036 b->v.ipaddress[1], b->v.ipaddress[2], b->v.ipaddress[3]); 1037 break; 1038 1039 case SNMP_SYNTAX_COUNTER: 1040 snmp_printf("COUNTER %u", b->v.uint32); 1041 break; 1042 1043 case SNMP_SYNTAX_GAUGE: 1044 snmp_printf("GAUGE %u", b->v.uint32); 1045 break; 1046 1047 case SNMP_SYNTAX_TIMETICKS: 1048 snmp_printf("TIMETICKS %u", b->v.uint32); 1049 break; 1050 1051 case SNMP_SYNTAX_COUNTER64: 1052 snmp_printf("COUNTER64 %lld", b->v.counter64); 1053 break; 1054 1055 case SNMP_SYNTAX_NOSUCHOBJECT: 1056 snmp_printf("NoSuchObject"); 1057 break; 1058 1059 case SNMP_SYNTAX_NOSUCHINSTANCE: 1060 snmp_printf("NoSuchInstance"); 1061 break; 1062 1063 case SNMP_SYNTAX_ENDOFMIBVIEW: 1064 snmp_printf("EndOfMibView"); 1065 break; 1066 1067 default: 1068 snmp_printf("UNKNOWN SYNTAX %u", b->syntax); 1069 break; 1070 } 1071 } 1072 1073 static __inline void 1074 dump_bindings(const struct snmp_pdu *pdu) 1075 { 1076 u_int i; 1077 1078 for (i = 0; i < pdu->nbindings; i++) { 1079 snmp_printf(" [%u]: ", i); 1080 dump_binding(&pdu->bindings[i]); 1081 snmp_printf("\n"); 1082 } 1083 } 1084 1085 static __inline void 1086 dump_notrap(const struct snmp_pdu *pdu) 1087 { 1088 snmp_printf(" request_id=%d", pdu->request_id); 1089 snmp_printf(" error_status=%d", pdu->error_status); 1090 snmp_printf(" error_index=%d\n", pdu->error_index); 1091 dump_bindings(pdu); 1092 } 1093 1094 void 1095 snmp_pdu_dump(const struct snmp_pdu *pdu) 1096 { 1097 char buf[ASN_OIDSTRLEN]; 1098 const char *vers; 1099 static const char *types[] = { 1100 [SNMP_PDU_GET] = "GET", 1101 [SNMP_PDU_GETNEXT] = "GETNEXT", 1102 [SNMP_PDU_RESPONSE] = "RESPONSE", 1103 [SNMP_PDU_SET] = "SET", 1104 [SNMP_PDU_TRAP] = "TRAPv1", 1105 [SNMP_PDU_GETBULK] = "GETBULK", 1106 [SNMP_PDU_INFORM] = "INFORM", 1107 [SNMP_PDU_TRAP2] = "TRAPv2", 1108 [SNMP_PDU_REPORT] = "REPORT", 1109 }; 1110 1111 if (pdu->version == SNMP_V1) 1112 vers = "SNMPv1"; 1113 else if (pdu->version == SNMP_V2c) 1114 vers = "SNMPv2c"; 1115 else if (pdu->version == SNMP_V3) 1116 vers = "SNMPv3"; 1117 else 1118 vers = "v?"; 1119 1120 switch (pdu->type) { 1121 case SNMP_PDU_TRAP: 1122 snmp_printf("%s %s '%s'", types[pdu->type], vers, pdu->community); 1123 snmp_printf(" enterprise=%s", asn_oid2str_r(&pdu->enterprise, buf)); 1124 snmp_printf(" agent_addr=%u.%u.%u.%u", pdu->agent_addr[0], 1125 pdu->agent_addr[1], pdu->agent_addr[2], pdu->agent_addr[3]); 1126 snmp_printf(" generic_trap=%d", pdu->generic_trap); 1127 snmp_printf(" specific_trap=%d", pdu->specific_trap); 1128 snmp_printf(" time-stamp=%u\n", pdu->time_stamp); 1129 dump_bindings(pdu); 1130 break; 1131 1132 case SNMP_PDU_GET: 1133 case SNMP_PDU_GETNEXT: 1134 case SNMP_PDU_RESPONSE: 1135 case SNMP_PDU_SET: 1136 case SNMP_PDU_GETBULK: 1137 case SNMP_PDU_INFORM: 1138 case SNMP_PDU_TRAP2: 1139 case SNMP_PDU_REPORT: 1140 snmp_printf("%s %s '%s'", types[pdu->type], vers, pdu->community); 1141 dump_notrap(pdu); 1142 break; 1143 1144 default: 1145 snmp_printf("bad pdu type %u\n", pdu->type); 1146 break; 1147 } 1148 } 1149 1150 void 1151 snmp_value_free(struct snmp_value *value) 1152 { 1153 if (value->syntax == SNMP_SYNTAX_OCTETSTRING) 1154 free(value->v.octetstring.octets); 1155 value->syntax = SNMP_SYNTAX_NULL; 1156 } 1157 1158 int 1159 snmp_value_copy(struct snmp_value *to, const struct snmp_value *from) 1160 { 1161 to->var = from->var; 1162 to->syntax = from->syntax; 1163 1164 if (from->syntax == SNMP_SYNTAX_OCTETSTRING) { 1165 if ((to->v.octetstring.len = from->v.octetstring.len) == 0) 1166 to->v.octetstring.octets = NULL; 1167 else { 1168 to->v.octetstring.octets = malloc(to->v.octetstring.len); 1169 if (to->v.octetstring.octets == NULL) 1170 return (-1); 1171 (void)memcpy(to->v.octetstring.octets, 1172 from->v.octetstring.octets, to->v.octetstring.len); 1173 } 1174 } else 1175 to->v = from->v; 1176 return (0); 1177 } 1178 1179 void 1180 snmp_pdu_init_secparams(struct snmp_pdu *pdu) 1181 { 1182 int32_t rval; 1183 1184 if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH) 1185 pdu->flags |= SNMP_MSG_AUTH_FLAG; 1186 1187 switch (pdu->user.priv_proto) { 1188 case SNMP_PRIV_DES: 1189 memcpy(pdu->msg_salt, &pdu->engine.engine_boots, 1190 sizeof(pdu->engine.engine_boots)); 1191 rval = random(); 1192 memcpy(pdu->msg_salt + sizeof(pdu->engine.engine_boots), &rval, 1193 sizeof(int32_t)); 1194 pdu->flags |= SNMP_MSG_PRIV_FLAG; 1195 break; 1196 case SNMP_PRIV_AES: 1197 rval = random(); 1198 memcpy(pdu->msg_salt, &rval, sizeof(int32_t)); 1199 rval = random(); 1200 memcpy(pdu->msg_salt + sizeof(int32_t), &rval, sizeof(int32_t)); 1201 pdu->flags |= SNMP_MSG_PRIV_FLAG; 1202 break; 1203 default: 1204 break; 1205 } 1206 } 1207 1208 void 1209 snmp_pdu_free(struct snmp_pdu *pdu) 1210 { 1211 u_int i; 1212 1213 for (i = 0; i < pdu->nbindings; i++) 1214 snmp_value_free(&pdu->bindings[i]); 1215 } 1216 1217 /* 1218 * Parse an ASCII SNMP value into the binary form 1219 */ 1220 int 1221 snmp_value_parse(const char *str, enum snmp_syntax syntax, union snmp_values *v) 1222 { 1223 char *end; 1224 1225 switch (syntax) { 1226 1227 case SNMP_SYNTAX_NULL: 1228 case SNMP_SYNTAX_NOSUCHOBJECT: 1229 case SNMP_SYNTAX_NOSUCHINSTANCE: 1230 case SNMP_SYNTAX_ENDOFMIBVIEW: 1231 if (*str != '\0') 1232 return (-1); 1233 return (0); 1234 1235 case SNMP_SYNTAX_INTEGER: 1236 v->integer = strtoll(str, &end, 0); 1237 if (*end != '\0') 1238 return (-1); 1239 return (0); 1240 1241 case SNMP_SYNTAX_OCTETSTRING: 1242 { 1243 u_long len; /* actual length of string */ 1244 u_long alloc; /* allocate length of string */ 1245 u_char *octs; /* actual octets */ 1246 u_long oct; /* actual octet */ 1247 u_char *nocts; /* to avoid memory leak */ 1248 u_char c; /* actual character */ 1249 1250 # define STUFFC(C) \ 1251 if (alloc == len) { \ 1252 alloc += 100; \ 1253 if ((nocts = realloc(octs, alloc)) == NULL) { \ 1254 free(octs); \ 1255 return (-1); \ 1256 } \ 1257 octs = nocts; \ 1258 } \ 1259 octs[len++] = (C); 1260 1261 len = alloc = 0; 1262 octs = NULL; 1263 1264 if (*str == '"') { 1265 str++; 1266 while((c = *str++) != '\0') { 1267 if (c == '"') { 1268 if (*str != '\0') { 1269 free(octs); 1270 return (-1); 1271 } 1272 break; 1273 } 1274 if (c == '\\') { 1275 switch (c = *str++) { 1276 1277 case '\\': 1278 break; 1279 case 'a': 1280 c = '\a'; 1281 break; 1282 case 'b': 1283 c = '\b'; 1284 break; 1285 case 'f': 1286 c = '\f'; 1287 break; 1288 case 'n': 1289 c = '\n'; 1290 break; 1291 case 'r': 1292 c = '\r'; 1293 break; 1294 case 't': 1295 c = '\t'; 1296 break; 1297 case 'v': 1298 c = '\v'; 1299 break; 1300 case 'x': 1301 c = 0; 1302 if (!isxdigit(*str)) 1303 break; 1304 if (isdigit(*str)) 1305 c = *str++ - '0'; 1306 else if (isupper(*str)) 1307 c = *str++ - 'A' + 10; 1308 else 1309 c = *str++ - 'a' + 10; 1310 if (!isxdigit(*str)) 1311 break; 1312 if (isdigit(*str)) 1313 c += *str++ - '0'; 1314 else if (isupper(*str)) 1315 c += *str++ - 'A' + 10; 1316 else 1317 c += *str++ - 'a' + 10; 1318 break; 1319 case '0': case '1': case '2': 1320 case '3': case '4': case '5': 1321 case '6': case '7': 1322 c = *str++ - '0'; 1323 if (*str < '0' || *str > '7') 1324 break; 1325 c = *str++ - '0'; 1326 if (*str < '0' || *str > '7') 1327 break; 1328 c = *str++ - '0'; 1329 break; 1330 default: 1331 break; 1332 } 1333 } 1334 STUFFC(c); 1335 } 1336 } else { 1337 while (*str != '\0') { 1338 oct = strtoul(str, &end, 16); 1339 str = end; 1340 if (oct > 0xff) { 1341 free(octs); 1342 return (-1); 1343 } 1344 STUFFC(oct); 1345 if (*str == ':') 1346 str++; 1347 else if(*str != '\0') { 1348 free(octs); 1349 return (-1); 1350 } 1351 } 1352 } 1353 v->octetstring.octets = octs; 1354 v->octetstring.len = len; 1355 return (0); 1356 # undef STUFFC 1357 } 1358 1359 case SNMP_SYNTAX_OID: 1360 { 1361 u_long subid; 1362 1363 v->oid.len = 0; 1364 1365 for (;;) { 1366 if (v->oid.len == ASN_MAXOIDLEN) 1367 return (-1); 1368 subid = strtoul(str, &end, 10); 1369 str = end; 1370 if (subid > ASN_MAXID) 1371 return (-1); 1372 v->oid.subs[v->oid.len++] = (asn_subid_t)subid; 1373 if (*str == '\0') 1374 break; 1375 if (*str != '.') 1376 return (-1); 1377 str++; 1378 } 1379 return (0); 1380 } 1381 1382 case SNMP_SYNTAX_IPADDRESS: 1383 { 1384 struct hostent *he; 1385 u_long ip[4]; 1386 int n; 1387 1388 if (sscanf(str, "%lu.%lu.%lu.%lu%n", &ip[0], &ip[1], &ip[2], 1389 &ip[3], &n) == 4 && (size_t)n == strlen(str) && 1390 ip[0] <= 0xff && ip[1] <= 0xff && 1391 ip[2] <= 0xff && ip[3] <= 0xff) { 1392 v->ipaddress[0] = (u_char)ip[0]; 1393 v->ipaddress[1] = (u_char)ip[1]; 1394 v->ipaddress[2] = (u_char)ip[2]; 1395 v->ipaddress[3] = (u_char)ip[3]; 1396 return (0); 1397 } 1398 1399 if ((he = gethostbyname(str)) == NULL) 1400 return (-1); 1401 if (he->h_addrtype != AF_INET) 1402 return (-1); 1403 1404 v->ipaddress[0] = he->h_addr[0]; 1405 v->ipaddress[1] = he->h_addr[1]; 1406 v->ipaddress[2] = he->h_addr[2]; 1407 v->ipaddress[3] = he->h_addr[3]; 1408 return (0); 1409 } 1410 1411 case SNMP_SYNTAX_COUNTER: 1412 case SNMP_SYNTAX_GAUGE: 1413 case SNMP_SYNTAX_TIMETICKS: 1414 { 1415 uint64_t sub; 1416 1417 sub = strtoull(str, &end, 0); 1418 if (*end != '\0' || sub > 0xffffffff) 1419 return (-1); 1420 v->uint32 = (uint32_t)sub; 1421 return (0); 1422 } 1423 1424 case SNMP_SYNTAX_COUNTER64: 1425 v->counter64 = strtoull(str, &end, 0); 1426 if (*end != '\0') 1427 return (-1); 1428 return (0); 1429 } 1430 abort(); 1431 } 1432 1433 static void 1434 snmp_error_func(const char *fmt, ...) 1435 { 1436 va_list ap; 1437 1438 va_start(ap, fmt); 1439 fprintf(stderr, "SNMP: "); 1440 vfprintf(stderr, fmt, ap); 1441 fprintf(stderr, "\n"); 1442 va_end(ap); 1443 } 1444 1445 static void 1446 snmp_printf_func(const char *fmt, ...) 1447 { 1448 va_list ap; 1449 1450 va_start(ap, fmt); 1451 vfprintf(stderr, fmt, ap); 1452 va_end(ap); 1453 } 1454