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 u_int len = 256; 292 293 if (asn_get_octetstring(b, buf, &len) != ASN_ERR_OK) { 294 snmp_error("cannot parse usm header"); 295 return (ASN_ERR_FAILED); 296 } 297 tb.asn_len = len; 298 299 if (asn_get_sequence(&tb, &octs_len) != ASN_ERR_OK) { 300 snmp_error("cannot decode usm header"); 301 return (ASN_ERR_FAILED); 302 } 303 304 octs_len = SNMP_ENGINE_ID_SIZ; 305 if (asn_get_octetstring(&tb, (u_char *)&pdu->engine.engine_id, 306 &octs_len) != ASN_ERR_OK) { 307 snmp_error("cannot decode msg engine id"); 308 return (ASN_ERR_FAILED); 309 } 310 pdu->engine.engine_len = octs_len; 311 312 if (asn_get_integer(&tb, &pdu->engine.engine_boots) != ASN_ERR_OK) { 313 snmp_error("cannot decode msg engine boots"); 314 return (ASN_ERR_FAILED); 315 } 316 317 if (asn_get_integer(&tb, &pdu->engine.engine_time) != ASN_ERR_OK) { 318 snmp_error("cannot decode msg engine time"); 319 return (ASN_ERR_FAILED); 320 } 321 322 octs_len = SNMP_ADM_STR32_SIZ - 1; 323 if (asn_get_octetstring(&tb, (u_char *)&pdu->user.sec_name, &octs_len) 324 != ASN_ERR_OK) { 325 snmp_error("cannot decode msg user name"); 326 return (ASN_ERR_FAILED); 327 } 328 pdu->user.sec_name[octs_len] = '\0'; 329 330 octs_len = sizeof(pdu->msg_digest); 331 if (asn_get_octetstring(&tb, (u_char *)&pdu->msg_digest, &octs_len) != 332 ASN_ERR_OK || ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0 && 333 octs_len != sizeof(pdu->msg_digest))) { 334 snmp_error("cannot decode msg authentication param"); 335 return (ASN_ERR_FAILED); 336 } 337 338 octs_len = sizeof(pdu->msg_salt); 339 if (asn_get_octetstring(&tb, (u_char *)&pdu->msg_salt, &octs_len) != 340 ASN_ERR_OK ||((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0 && 341 octs_len != sizeof(pdu->msg_salt))) { 342 snmp_error("cannot decode msg authentication param"); 343 return (ASN_ERR_FAILED); 344 } 345 346 if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) { 347 pdu->digest_ptr = b->asn_ptr - SNMP_USM_AUTH_SIZE; 348 pdu->digest_ptr -= octs_len + ASN_MAXLENLEN; 349 } 350 351 return (ASN_ERR_OK); 352 } 353 354 static enum snmp_code 355 pdu_encode_secparams(struct asn_buf *b, struct snmp_pdu *pdu) 356 { 357 u_char buf[256], *sptr; 358 struct asn_buf tb; 359 size_t auth_off, moved = 0; 360 361 auth_off = 0; 362 memset(buf, 0, 256); 363 tb.asn_ptr = buf; 364 tb.asn_len = 256; 365 366 if (asn_put_temp_header(&tb, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED), 367 &sptr) != ASN_ERR_OK) 368 return (SNMP_CODE_FAILED); 369 370 if (asn_put_octetstring(&tb, (u_char *)pdu->engine.engine_id, 371 pdu->engine.engine_len) != ASN_ERR_OK) 372 return (SNMP_CODE_FAILED); 373 374 if (asn_put_integer(&tb, pdu->engine.engine_boots) != ASN_ERR_OK) 375 return (SNMP_CODE_FAILED); 376 377 if (asn_put_integer(&tb, pdu->engine.engine_time) != ASN_ERR_OK) 378 return (SNMP_CODE_FAILED); 379 380 if (asn_put_octetstring(&tb, (u_char *)pdu->user.sec_name, 381 strlen(pdu->user.sec_name)) != ASN_ERR_OK) 382 return (SNMP_CODE_FAILED); 383 384 if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) { 385 auth_off = sizeof(buf) - tb.asn_len + ASN_MAXLENLEN; 386 if (asn_put_octetstring(&tb, (u_char *)pdu->msg_digest, 387 sizeof(pdu->msg_digest)) != ASN_ERR_OK) 388 return (SNMP_CODE_FAILED); 389 } else { 390 if (asn_put_octetstring(&tb, (u_char *)pdu->msg_digest, 0) 391 != ASN_ERR_OK) 392 return (SNMP_CODE_FAILED); 393 } 394 395 if ((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0) { 396 if (asn_put_octetstring(&tb, (u_char *)pdu->msg_salt, 397 sizeof(pdu->msg_salt)) != ASN_ERR_OK) 398 return (SNMP_CODE_FAILED); 399 } else { 400 if (asn_put_octetstring(&tb, (u_char *)pdu->msg_salt, 0) 401 != ASN_ERR_OK) 402 return (SNMP_CODE_FAILED); 403 } 404 405 if (asn_commit_header(&tb, sptr, &moved) != ASN_ERR_OK) 406 return (SNMP_CODE_FAILED); 407 408 if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) 409 pdu->digest_ptr = b->asn_ptr + auth_off - moved; 410 411 if (asn_put_octetstring(b, buf, sizeof(buf) - tb.asn_len) != ASN_ERR_OK) 412 return (SNMP_CODE_FAILED); 413 pdu->digest_ptr += ASN_MAXLENLEN; 414 415 if ((pdu->flags & SNMP_MSG_PRIV_FLAG) != 0 && asn_put_temp_header(b, 416 ASN_TYPE_OCTETSTRING, &pdu->encrypted_ptr) != ASN_ERR_OK) 417 return (SNMP_CODE_FAILED); 418 419 return (SNMP_CODE_OK); 420 } 421 422 /* 423 * Decode the PDU except for the variable bindings itself. 424 * If decoding fails because of a bad binding, but the rest can be 425 * decoded, ip points to the index of the failed variable (errors 426 * OORANGE, BADLEN or BADVERS). 427 */ 428 enum snmp_code 429 snmp_pdu_decode(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip) 430 { 431 enum snmp_code code; 432 433 if ((code = snmp_pdu_decode_header(b, pdu)) != SNMP_CODE_OK) 434 return (code); 435 436 if (pdu->version == SNMP_V3) { 437 if (pdu->security_model != SNMP_SECMODEL_USM) 438 return (SNMP_CODE_FAILED); 439 if ((code = snmp_pdu_decode_secmode(b, pdu)) != SNMP_CODE_OK) 440 return (code); 441 } 442 443 code = snmp_pdu_decode_scoped(b, pdu, ip); 444 445 switch (code) { 446 case SNMP_CODE_FAILED: 447 snmp_pdu_free(pdu); 448 break; 449 450 case SNMP_CODE_BADENC: 451 if (pdu->version == SNMP_Verr) 452 return (SNMP_CODE_BADVERS); 453 454 default: 455 break; 456 } 457 458 return (code); 459 } 460 461 enum snmp_code 462 snmp_pdu_decode_header(struct asn_buf *b, struct snmp_pdu *pdu) 463 { 464 int32_t version; 465 u_int octs_len; 466 asn_len_t len; 467 468 pdu->outer_ptr = b->asn_ptr; 469 pdu->outer_len = b->asn_len; 470 471 if (asn_get_sequence(b, &len) != ASN_ERR_OK) { 472 snmp_error("cannot decode pdu header"); 473 return (SNMP_CODE_FAILED); 474 } 475 if (b->asn_len < len) { 476 snmp_error("outer sequence value too short"); 477 return (SNMP_CODE_FAILED); 478 } 479 if (b->asn_len != len) { 480 snmp_error("ignoring trailing junk in message"); 481 b->asn_len = len; 482 } 483 484 if (asn_get_integer(b, &version) != ASN_ERR_OK) { 485 snmp_error("cannot decode version"); 486 return (SNMP_CODE_FAILED); 487 } 488 489 if (version == 0) 490 pdu->version = SNMP_V1; 491 else if (version == 1) 492 pdu->version = SNMP_V2c; 493 else if (version == 3) 494 pdu->version = SNMP_V3; 495 else { 496 pdu->version = SNMP_Verr; 497 snmp_error("unsupported SNMP version"); 498 return (SNMP_CODE_BADENC); 499 } 500 501 if (pdu->version == SNMP_V3) { 502 if (asn_get_sequence(b, &len) != ASN_ERR_OK) { 503 snmp_error("cannot decode pdu global data header"); 504 return (SNMP_CODE_FAILED); 505 } 506 507 if (asn_get_integer(b, &pdu->identifier) != ASN_ERR_OK) { 508 snmp_error("cannot decode msg indetifier"); 509 return (SNMP_CODE_FAILED); 510 } 511 512 if (asn_get_integer(b, &pdu->engine.max_msg_size) 513 != ASN_ERR_OK) { 514 snmp_error("cannot decode msg size"); 515 return (SNMP_CODE_FAILED); 516 } 517 518 octs_len = 1; 519 if (asn_get_octetstring(b, (u_char *)&pdu->flags, 520 &octs_len) != ASN_ERR_OK) { 521 snmp_error("cannot decode msg flags"); 522 return (SNMP_CODE_FAILED); 523 } 524 525 if (asn_get_integer(b, &pdu->security_model) != ASN_ERR_OK) { 526 snmp_error("cannot decode msg size"); 527 return (SNMP_CODE_FAILED); 528 } 529 530 if (pdu->security_model != SNMP_SECMODEL_USM) 531 return (SNMP_CODE_FAILED); 532 533 if (parse_secparams(b, pdu) != ASN_ERR_OK) 534 return (SNMP_CODE_FAILED); 535 } else { 536 octs_len = SNMP_COMMUNITY_MAXLEN; 537 if (asn_get_octetstring(b, (u_char *)pdu->community, 538 &octs_len) != ASN_ERR_OK) { 539 snmp_error("cannot decode community"); 540 return (SNMP_CODE_FAILED); 541 } 542 pdu->community[octs_len] = '\0'; 543 } 544 545 return (SNMP_CODE_OK); 546 } 547 548 enum snmp_code 549 snmp_pdu_decode_scoped(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *ip) 550 { 551 u_char type; 552 asn_len_t len, trailer; 553 enum asn_err err; 554 555 if (pdu->version == SNMP_V3) { 556 if (asn_get_sequence(b, &len) != ASN_ERR_OK) { 557 snmp_error("cannot decode scoped pdu header"); 558 return (SNMP_CODE_FAILED); 559 } 560 561 len = SNMP_ENGINE_ID_SIZ; 562 if (asn_get_octetstring(b, (u_char *)&pdu->context_engine, 563 &len) != ASN_ERR_OK) { 564 snmp_error("cannot decode msg context engine"); 565 return (SNMP_CODE_FAILED); 566 } 567 pdu->context_engine_len = len; 568 569 len = SNMP_CONTEXT_NAME_SIZ; 570 if (asn_get_octetstring(b, (u_char *)&pdu->context_name, 571 &len) != ASN_ERR_OK) { 572 snmp_error("cannot decode msg context name"); 573 return (SNMP_CODE_FAILED); 574 } 575 pdu->context_name[len] = '\0'; 576 } 577 578 if (asn_get_header(b, &type, &len) != ASN_ERR_OK) { 579 snmp_error("cannot get pdu header"); 580 return (SNMP_CODE_FAILED); 581 } 582 if ((type & ~ASN_TYPE_MASK) != 583 (ASN_TYPE_CONSTRUCTED | ASN_CLASS_CONTEXT)) { 584 snmp_error("bad pdu header tag"); 585 return (SNMP_CODE_FAILED); 586 } 587 pdu->type = type & ASN_TYPE_MASK; 588 589 switch (pdu->type) { 590 591 case SNMP_PDU_GET: 592 case SNMP_PDU_GETNEXT: 593 case SNMP_PDU_RESPONSE: 594 case SNMP_PDU_SET: 595 break; 596 597 case SNMP_PDU_TRAP: 598 if (pdu->version != SNMP_V1) { 599 snmp_error("bad pdu type %u", pdu->type); 600 return (SNMP_CODE_FAILED); 601 } 602 break; 603 604 case SNMP_PDU_GETBULK: 605 case SNMP_PDU_INFORM: 606 case SNMP_PDU_TRAP2: 607 case SNMP_PDU_REPORT: 608 if (pdu->version == SNMP_V1) { 609 snmp_error("bad pdu type %u", pdu->type); 610 return (SNMP_CODE_FAILED); 611 } 612 break; 613 614 default: 615 snmp_error("bad pdu type %u", pdu->type); 616 return (SNMP_CODE_FAILED); 617 } 618 619 trailer = b->asn_len - len; 620 b->asn_len = len; 621 622 err = parse_pdus(b, pdu, ip); 623 if (ASN_ERR_STOPPED(err)) 624 return (SNMP_CODE_FAILED); 625 626 if (b->asn_len != 0) 627 snmp_error("ignoring trailing junk after pdu"); 628 629 b->asn_len = trailer; 630 631 return (SNMP_CODE_OK); 632 } 633 634 enum snmp_code 635 snmp_pdu_decode_secmode(struct asn_buf *b, struct snmp_pdu *pdu) 636 { 637 u_char type; 638 enum snmp_code code; 639 uint8_t digest[SNMP_USM_AUTH_SIZE]; 640 641 if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH && 642 (pdu->flags & SNMP_MSG_AUTH_FLAG) == 0) 643 return (SNMP_CODE_BADSECLEVEL); 644 645 if ((code = snmp_pdu_calc_digest(pdu, digest)) != 646 SNMP_CODE_OK) 647 return (SNMP_CODE_FAILED); 648 649 if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH && 650 memcmp(digest, pdu->msg_digest, sizeof(pdu->msg_digest)) != 0) 651 return (SNMP_CODE_BADDIGEST); 652 653 if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV && (asn_get_header(b, &type, 654 &pdu->scoped_len) != ASN_ERR_OK || type != ASN_TYPE_OCTETSTRING)) { 655 snmp_error("cannot decode encrypted pdu"); 656 return (SNMP_CODE_FAILED); 657 } 658 pdu->scoped_ptr = b->asn_ptr; 659 660 if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV && 661 (pdu->flags & SNMP_MSG_PRIV_FLAG) == 0) 662 return (SNMP_CODE_BADSECLEVEL); 663 664 if ((code = snmp_pdu_decrypt(pdu)) != SNMP_CODE_OK) 665 return (SNMP_CODE_FAILED); 666 667 return (code); 668 } 669 670 /* 671 * Check whether what we have is the complete PDU by snooping at the 672 * enclosing structure header. This returns: 673 * -1 if there are ASN.1 errors 674 * 0 if we need more data 675 * > 0 the length of this PDU 676 */ 677 int 678 snmp_pdu_snoop(const struct asn_buf *b0) 679 { 680 u_int length; 681 asn_len_t len; 682 struct asn_buf b = *b0; 683 684 /* <0x10|0x20> <len> <data...> */ 685 686 if (b.asn_len == 0) 687 return (0); 688 if (b.asn_cptr[0] != (ASN_TYPE_SEQUENCE | ASN_TYPE_CONSTRUCTED)) { 689 asn_error(&b, "bad sequence type %u", b.asn_cptr[0]); 690 return (-1); 691 } 692 b.asn_len--; 693 b.asn_cptr++; 694 695 if (b.asn_len == 0) 696 return (0); 697 698 if (*b.asn_cptr & 0x80) { 699 /* long length */ 700 length = *b.asn_cptr++ & 0x7f; 701 b.asn_len--; 702 if (length == 0) { 703 asn_error(&b, "indefinite length not supported"); 704 return (-1); 705 } 706 if (length > ASN_MAXLENLEN) { 707 asn_error(&b, "long length too long (%u)", length); 708 return (-1); 709 } 710 if (length > b.asn_len) 711 return (0); 712 len = 0; 713 while (length--) { 714 len = (len << 8) | *b.asn_cptr++; 715 b.asn_len--; 716 } 717 } else { 718 len = *b.asn_cptr++; 719 b.asn_len--; 720 } 721 722 if (len > b.asn_len) 723 return (0); 724 725 return (len + b.asn_cptr - b0->asn_cptr); 726 } 727 728 /* 729 * Encode the SNMP PDU without the variable bindings field. 730 * We do this the rather uneffective way by 731 * moving things around and assuming that the length field will never 732 * use more than 2 bytes. 733 * We need a number of pointers to apply the fixes afterwards. 734 */ 735 enum snmp_code 736 snmp_pdu_encode_header(struct asn_buf *b, struct snmp_pdu *pdu) 737 { 738 enum asn_err err; 739 u_char *v3_hdr_ptr; 740 741 if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED), 742 &pdu->outer_ptr) != ASN_ERR_OK) 743 return (SNMP_CODE_FAILED); 744 745 if (pdu->version == SNMP_V1) 746 err = asn_put_integer(b, 0); 747 else if (pdu->version == SNMP_V2c) 748 err = asn_put_integer(b, 1); 749 else if (pdu->version == SNMP_V3) 750 err = asn_put_integer(b, 3); 751 else 752 return (SNMP_CODE_BADVERS); 753 if (err != ASN_ERR_OK) 754 return (SNMP_CODE_FAILED); 755 756 if (pdu->version == SNMP_V3) { 757 if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE | 758 ASN_TYPE_CONSTRUCTED), &v3_hdr_ptr) != ASN_ERR_OK) 759 return (SNMP_CODE_FAILED); 760 761 if (asn_put_integer(b, pdu->identifier) != ASN_ERR_OK) 762 return (SNMP_CODE_FAILED); 763 764 if (asn_put_integer(b, pdu->engine.max_msg_size) != ASN_ERR_OK) 765 return (SNMP_CODE_FAILED); 766 767 if (pdu->type != SNMP_PDU_RESPONSE && 768 pdu->type != SNMP_PDU_TRAP && 769 pdu->type != SNMP_PDU_TRAP2 && 770 pdu->type != SNMP_PDU_REPORT) 771 pdu->flags |= SNMP_MSG_REPORT_FLAG; 772 773 if (asn_put_octetstring(b, (u_char *)&pdu->flags, 1) 774 != ASN_ERR_OK) 775 return (SNMP_CODE_FAILED); 776 777 if (asn_put_integer(b, pdu->security_model) != ASN_ERR_OK) 778 return (SNMP_CODE_FAILED); 779 780 if (asn_commit_header(b, v3_hdr_ptr, NULL) != ASN_ERR_OK) 781 return (SNMP_CODE_FAILED); 782 783 if (pdu->security_model != SNMP_SECMODEL_USM) 784 return (SNMP_CODE_FAILED); 785 786 if (pdu_encode_secparams(b, pdu) != SNMP_CODE_OK) 787 return (SNMP_CODE_FAILED); 788 789 /* View-based Access Conntrol information */ 790 if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE | 791 ASN_TYPE_CONSTRUCTED), &pdu->scoped_ptr) != ASN_ERR_OK) 792 return (SNMP_CODE_FAILED); 793 794 if (asn_put_octetstring(b, (u_char *)pdu->context_engine, 795 pdu->context_engine_len) != ASN_ERR_OK) 796 return (SNMP_CODE_FAILED); 797 798 if (asn_put_octetstring(b, (u_char *)pdu->context_name, 799 strlen(pdu->context_name)) != ASN_ERR_OK) 800 return (SNMP_CODE_FAILED); 801 } else { 802 if (asn_put_octetstring(b, (u_char *)pdu->community, 803 strlen(pdu->community)) != ASN_ERR_OK) 804 return (SNMP_CODE_FAILED); 805 } 806 807 if (asn_put_temp_header(b, (ASN_TYPE_CONSTRUCTED | ASN_CLASS_CONTEXT | 808 pdu->type), &pdu->pdu_ptr) != ASN_ERR_OK) 809 return (SNMP_CODE_FAILED); 810 811 if (pdu->type == SNMP_PDU_TRAP) { 812 if (pdu->version != SNMP_V1 || 813 asn_put_objid(b, &pdu->enterprise) != ASN_ERR_OK || 814 asn_put_ipaddress(b, pdu->agent_addr) != ASN_ERR_OK || 815 asn_put_integer(b, pdu->generic_trap) != ASN_ERR_OK || 816 asn_put_integer(b, pdu->specific_trap) != ASN_ERR_OK || 817 asn_put_timeticks(b, pdu->time_stamp) != ASN_ERR_OK) 818 return (SNMP_CODE_FAILED); 819 } else { 820 if (pdu->version == SNMP_V1 && (pdu->type == SNMP_PDU_GETBULK || 821 pdu->type == SNMP_PDU_INFORM || 822 pdu->type == SNMP_PDU_TRAP2 || 823 pdu->type == SNMP_PDU_REPORT)) 824 return (SNMP_CODE_FAILED); 825 826 if (asn_put_integer(b, pdu->request_id) != ASN_ERR_OK || 827 asn_put_integer(b, pdu->error_status) != ASN_ERR_OK || 828 asn_put_integer(b, pdu->error_index) != ASN_ERR_OK) 829 return (SNMP_CODE_FAILED); 830 } 831 832 if (asn_put_temp_header(b, (ASN_TYPE_SEQUENCE|ASN_TYPE_CONSTRUCTED), 833 &pdu->vars_ptr) != ASN_ERR_OK) 834 return (SNMP_CODE_FAILED); 835 836 return (SNMP_CODE_OK); 837 } 838 839 static enum asn_err 840 snmp_pdu_fix_padd(struct asn_buf *b, struct snmp_pdu *pdu) 841 { 842 asn_len_t padlen; 843 844 if (pdu->user.priv_proto == SNMP_PRIV_DES && pdu->scoped_len % 8 != 0) { 845 padlen = 8 - (pdu->scoped_len % 8); 846 if (asn_pad(b, padlen) != ASN_ERR_OK) 847 return (ASN_ERR_FAILED); 848 pdu->scoped_len += padlen; 849 } 850 851 return (ASN_ERR_OK); 852 } 853 854 enum snmp_code 855 snmp_fix_encoding(struct asn_buf *b, struct snmp_pdu *pdu) 856 { 857 size_t moved = 0; 858 enum snmp_code code; 859 860 if (asn_commit_header(b, pdu->vars_ptr, NULL) != ASN_ERR_OK || 861 asn_commit_header(b, pdu->pdu_ptr, NULL) != ASN_ERR_OK) 862 return (SNMP_CODE_FAILED); 863 864 if (pdu->version == SNMP_V3) { 865 if (asn_commit_header(b, pdu->scoped_ptr, NULL) != ASN_ERR_OK) 866 return (SNMP_CODE_FAILED); 867 868 pdu->scoped_len = b->asn_ptr - pdu->scoped_ptr; 869 if (snmp_pdu_fix_padd(b, pdu) != ASN_ERR_OK) 870 return (SNMP_CODE_FAILED); 871 872 if (pdu->security_model != SNMP_SECMODEL_USM) 873 return (SNMP_CODE_FAILED); 874 875 if (snmp_pdu_encrypt(pdu) != SNMP_CODE_OK) 876 return (SNMP_CODE_FAILED); 877 878 if (pdu->user.priv_proto != SNMP_PRIV_NOPRIV && 879 asn_commit_header(b, pdu->encrypted_ptr, NULL) != ASN_ERR_OK) 880 return (SNMP_CODE_FAILED); 881 } 882 883 if (asn_commit_header(b, pdu->outer_ptr, &moved) != ASN_ERR_OK) 884 return (SNMP_CODE_FAILED); 885 886 pdu->outer_len = b->asn_ptr - pdu->outer_ptr; 887 pdu->digest_ptr -= moved; 888 889 if (pdu->version == SNMP_V3) { 890 if ((code = snmp_pdu_calc_digest(pdu, pdu->msg_digest)) != 891 SNMP_CODE_OK) 892 return (SNMP_CODE_FAILED); 893 894 if ((pdu->flags & SNMP_MSG_AUTH_FLAG) != 0) 895 memcpy(pdu->digest_ptr, pdu->msg_digest, 896 sizeof(pdu->msg_digest)); 897 } 898 899 return (SNMP_CODE_OK); 900 } 901 902 /* 903 * Encode a binding. Caller must ensure, that the syntax is ok for that version. 904 * Be sure not to cobber b, when something fails. 905 */ 906 enum asn_err 907 snmp_binding_encode(struct asn_buf *b, const struct snmp_value *binding) 908 { 909 u_char *ptr; 910 enum asn_err err; 911 struct asn_buf save = *b; 912 913 if ((err = asn_put_temp_header(b, (ASN_TYPE_SEQUENCE | 914 ASN_TYPE_CONSTRUCTED), &ptr)) != ASN_ERR_OK) { 915 *b = save; 916 return (err); 917 } 918 919 if ((err = asn_put_objid(b, &binding->var)) != ASN_ERR_OK) { 920 *b = save; 921 return (err); 922 } 923 924 switch (binding->syntax) { 925 926 case SNMP_SYNTAX_NULL: 927 err = asn_put_null(b); 928 break; 929 930 case SNMP_SYNTAX_INTEGER: 931 err = asn_put_integer(b, binding->v.integer); 932 break; 933 934 case SNMP_SYNTAX_OCTETSTRING: 935 err = asn_put_octetstring(b, binding->v.octetstring.octets, 936 binding->v.octetstring.len); 937 break; 938 939 case SNMP_SYNTAX_OID: 940 err = asn_put_objid(b, &binding->v.oid); 941 break; 942 943 case SNMP_SYNTAX_IPADDRESS: 944 err = asn_put_ipaddress(b, binding->v.ipaddress); 945 break; 946 947 case SNMP_SYNTAX_TIMETICKS: 948 err = asn_put_uint32(b, ASN_APP_TIMETICKS, binding->v.uint32); 949 break; 950 951 case SNMP_SYNTAX_COUNTER: 952 err = asn_put_uint32(b, ASN_APP_COUNTER, binding->v.uint32); 953 break; 954 955 case SNMP_SYNTAX_GAUGE: 956 err = asn_put_uint32(b, ASN_APP_GAUGE, binding->v.uint32); 957 break; 958 959 case SNMP_SYNTAX_COUNTER64: 960 err = asn_put_counter64(b, binding->v.counter64); 961 break; 962 963 case SNMP_SYNTAX_NOSUCHOBJECT: 964 err = asn_put_exception(b, ASN_EXCEPT_NOSUCHOBJECT); 965 break; 966 967 case SNMP_SYNTAX_NOSUCHINSTANCE: 968 err = asn_put_exception(b, ASN_EXCEPT_NOSUCHINSTANCE); 969 break; 970 971 case SNMP_SYNTAX_ENDOFMIBVIEW: 972 err = asn_put_exception(b, ASN_EXCEPT_ENDOFMIBVIEW); 973 break; 974 } 975 976 if (err != ASN_ERR_OK) { 977 *b = save; 978 return (err); 979 } 980 981 err = asn_commit_header(b, ptr, NULL); 982 if (err != ASN_ERR_OK) { 983 *b = save; 984 return (err); 985 } 986 987 return (ASN_ERR_OK); 988 } 989 990 /* 991 * Encode an PDU. 992 */ 993 enum snmp_code 994 snmp_pdu_encode(struct snmp_pdu *pdu, struct asn_buf *resp_b) 995 { 996 u_int idx; 997 enum snmp_code err; 998 999 if ((err = snmp_pdu_encode_header(resp_b, pdu)) != SNMP_CODE_OK) 1000 return (err); 1001 for (idx = 0; idx < pdu->nbindings; idx++) 1002 if (snmp_binding_encode(resp_b, &pdu->bindings[idx]) 1003 != ASN_ERR_OK) 1004 return (SNMP_CODE_FAILED); 1005 1006 return (snmp_fix_encoding(resp_b, pdu)); 1007 } 1008 1009 static void 1010 dump_binding(const struct snmp_value *b) 1011 { 1012 u_int i; 1013 char buf[ASN_OIDSTRLEN]; 1014 1015 snmp_printf("%s=", asn_oid2str_r(&b->var, buf)); 1016 switch (b->syntax) { 1017 1018 case SNMP_SYNTAX_NULL: 1019 snmp_printf("NULL"); 1020 break; 1021 1022 case SNMP_SYNTAX_INTEGER: 1023 snmp_printf("INTEGER %d", b->v.integer); 1024 break; 1025 1026 case SNMP_SYNTAX_OCTETSTRING: 1027 snmp_printf("OCTET STRING %lu:", b->v.octetstring.len); 1028 for (i = 0; i < b->v.octetstring.len; i++) 1029 snmp_printf(" %02x", b->v.octetstring.octets[i]); 1030 break; 1031 1032 case SNMP_SYNTAX_OID: 1033 snmp_printf("OID %s", asn_oid2str_r(&b->v.oid, buf)); 1034 break; 1035 1036 case SNMP_SYNTAX_IPADDRESS: 1037 snmp_printf("IPADDRESS %u.%u.%u.%u", b->v.ipaddress[0], 1038 b->v.ipaddress[1], b->v.ipaddress[2], b->v.ipaddress[3]); 1039 break; 1040 1041 case SNMP_SYNTAX_COUNTER: 1042 snmp_printf("COUNTER %u", b->v.uint32); 1043 break; 1044 1045 case SNMP_SYNTAX_GAUGE: 1046 snmp_printf("GAUGE %u", b->v.uint32); 1047 break; 1048 1049 case SNMP_SYNTAX_TIMETICKS: 1050 snmp_printf("TIMETICKS %u", b->v.uint32); 1051 break; 1052 1053 case SNMP_SYNTAX_COUNTER64: 1054 snmp_printf("COUNTER64 %lld", b->v.counter64); 1055 break; 1056 1057 case SNMP_SYNTAX_NOSUCHOBJECT: 1058 snmp_printf("NoSuchObject"); 1059 break; 1060 1061 case SNMP_SYNTAX_NOSUCHINSTANCE: 1062 snmp_printf("NoSuchInstance"); 1063 break; 1064 1065 case SNMP_SYNTAX_ENDOFMIBVIEW: 1066 snmp_printf("EndOfMibView"); 1067 break; 1068 1069 default: 1070 snmp_printf("UNKNOWN SYNTAX %u", b->syntax); 1071 break; 1072 } 1073 } 1074 1075 static __inline void 1076 dump_bindings(const struct snmp_pdu *pdu) 1077 { 1078 u_int i; 1079 1080 for (i = 0; i < pdu->nbindings; i++) { 1081 snmp_printf(" [%u]: ", i); 1082 dump_binding(&pdu->bindings[i]); 1083 snmp_printf("\n"); 1084 } 1085 } 1086 1087 static __inline void 1088 dump_notrap(const struct snmp_pdu *pdu) 1089 { 1090 snmp_printf(" request_id=%d", pdu->request_id); 1091 snmp_printf(" error_status=%d", pdu->error_status); 1092 snmp_printf(" error_index=%d\n", pdu->error_index); 1093 dump_bindings(pdu); 1094 } 1095 1096 void 1097 snmp_pdu_dump(const struct snmp_pdu *pdu) 1098 { 1099 char buf[ASN_OIDSTRLEN]; 1100 const char *vers; 1101 static const char *types[] = { 1102 [SNMP_PDU_GET] = "GET", 1103 [SNMP_PDU_GETNEXT] = "GETNEXT", 1104 [SNMP_PDU_RESPONSE] = "RESPONSE", 1105 [SNMP_PDU_SET] = "SET", 1106 [SNMP_PDU_TRAP] = "TRAPv1", 1107 [SNMP_PDU_GETBULK] = "GETBULK", 1108 [SNMP_PDU_INFORM] = "INFORM", 1109 [SNMP_PDU_TRAP2] = "TRAPv2", 1110 [SNMP_PDU_REPORT] = "REPORT", 1111 }; 1112 1113 if (pdu->version == SNMP_V1) 1114 vers = "SNMPv1"; 1115 else if (pdu->version == SNMP_V2c) 1116 vers = "SNMPv2c"; 1117 else if (pdu->version == SNMP_V3) 1118 vers = "SNMPv3"; 1119 else 1120 vers = "v?"; 1121 1122 switch (pdu->type) { 1123 case SNMP_PDU_TRAP: 1124 snmp_printf("%s %s '%s'", types[pdu->type], vers, pdu->community); 1125 snmp_printf(" enterprise=%s", asn_oid2str_r(&pdu->enterprise, buf)); 1126 snmp_printf(" agent_addr=%u.%u.%u.%u", pdu->agent_addr[0], 1127 pdu->agent_addr[1], pdu->agent_addr[2], pdu->agent_addr[3]); 1128 snmp_printf(" generic_trap=%d", pdu->generic_trap); 1129 snmp_printf(" specific_trap=%d", pdu->specific_trap); 1130 snmp_printf(" time-stamp=%u\n", pdu->time_stamp); 1131 dump_bindings(pdu); 1132 break; 1133 1134 case SNMP_PDU_GET: 1135 case SNMP_PDU_GETNEXT: 1136 case SNMP_PDU_RESPONSE: 1137 case SNMP_PDU_SET: 1138 case SNMP_PDU_GETBULK: 1139 case SNMP_PDU_INFORM: 1140 case SNMP_PDU_TRAP2: 1141 case SNMP_PDU_REPORT: 1142 snmp_printf("%s %s '%s'", types[pdu->type], vers, pdu->community); 1143 dump_notrap(pdu); 1144 break; 1145 1146 default: 1147 snmp_printf("bad pdu type %u\n", pdu->type); 1148 break; 1149 } 1150 } 1151 1152 void 1153 snmp_value_free(struct snmp_value *value) 1154 { 1155 if (value->syntax == SNMP_SYNTAX_OCTETSTRING) 1156 free(value->v.octetstring.octets); 1157 value->syntax = SNMP_SYNTAX_NULL; 1158 } 1159 1160 int 1161 snmp_value_copy(struct snmp_value *to, const struct snmp_value *from) 1162 { 1163 to->var = from->var; 1164 to->syntax = from->syntax; 1165 1166 if (from->syntax == SNMP_SYNTAX_OCTETSTRING) { 1167 if ((to->v.octetstring.len = from->v.octetstring.len) == 0) 1168 to->v.octetstring.octets = NULL; 1169 else { 1170 to->v.octetstring.octets = malloc(to->v.octetstring.len); 1171 if (to->v.octetstring.octets == NULL) 1172 return (-1); 1173 (void)memcpy(to->v.octetstring.octets, 1174 from->v.octetstring.octets, to->v.octetstring.len); 1175 } 1176 } else 1177 to->v = from->v; 1178 return (0); 1179 } 1180 1181 void 1182 snmp_pdu_init_secparams(struct snmp_pdu *pdu) 1183 { 1184 int32_t rval; 1185 1186 if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH) 1187 pdu->flags |= SNMP_MSG_AUTH_FLAG; 1188 1189 switch (pdu->user.priv_proto) { 1190 case SNMP_PRIV_DES: 1191 memcpy(pdu->msg_salt, &pdu->engine.engine_boots, 1192 sizeof(pdu->engine.engine_boots)); 1193 rval = random(); 1194 memcpy(pdu->msg_salt + sizeof(pdu->engine.engine_boots), &rval, 1195 sizeof(int32_t)); 1196 pdu->flags |= SNMP_MSG_PRIV_FLAG; 1197 break; 1198 case SNMP_PRIV_AES: 1199 rval = random(); 1200 memcpy(pdu->msg_salt, &rval, sizeof(int32_t)); 1201 rval = random(); 1202 memcpy(pdu->msg_salt + sizeof(int32_t), &rval, sizeof(int32_t)); 1203 pdu->flags |= SNMP_MSG_PRIV_FLAG; 1204 break; 1205 default: 1206 break; 1207 } 1208 } 1209 1210 void 1211 snmp_pdu_free(struct snmp_pdu *pdu) 1212 { 1213 u_int i; 1214 1215 for (i = 0; i < pdu->nbindings; i++) 1216 snmp_value_free(&pdu->bindings[i]); 1217 } 1218 1219 /* 1220 * Parse an ASCII SNMP value into the binary form 1221 */ 1222 int 1223 snmp_value_parse(const char *str, enum snmp_syntax syntax, union snmp_values *v) 1224 { 1225 char *end; 1226 1227 switch (syntax) { 1228 1229 case SNMP_SYNTAX_NULL: 1230 case SNMP_SYNTAX_NOSUCHOBJECT: 1231 case SNMP_SYNTAX_NOSUCHINSTANCE: 1232 case SNMP_SYNTAX_ENDOFMIBVIEW: 1233 if (*str != '\0') 1234 return (-1); 1235 return (0); 1236 1237 case SNMP_SYNTAX_INTEGER: 1238 v->integer = strtoll(str, &end, 0); 1239 if (*end != '\0') 1240 return (-1); 1241 return (0); 1242 1243 case SNMP_SYNTAX_OCTETSTRING: 1244 { 1245 u_long len; /* actual length of string */ 1246 u_long alloc; /* allocate length of string */ 1247 u_char *octs; /* actual octets */ 1248 u_long oct; /* actual octet */ 1249 u_char *nocts; /* to avoid memory leak */ 1250 u_char c; /* actual character */ 1251 1252 # define STUFFC(C) \ 1253 if (alloc == len) { \ 1254 alloc += 100; \ 1255 if ((nocts = realloc(octs, alloc)) == NULL) { \ 1256 free(octs); \ 1257 return (-1); \ 1258 } \ 1259 octs = nocts; \ 1260 } \ 1261 octs[len++] = (C); 1262 1263 len = alloc = 0; 1264 octs = NULL; 1265 1266 if (*str == '"') { 1267 str++; 1268 while((c = *str++) != '\0') { 1269 if (c == '"') { 1270 if (*str != '\0') { 1271 free(octs); 1272 return (-1); 1273 } 1274 break; 1275 } 1276 if (c == '\\') { 1277 switch (c = *str++) { 1278 1279 case '\\': 1280 break; 1281 case 'a': 1282 c = '\a'; 1283 break; 1284 case 'b': 1285 c = '\b'; 1286 break; 1287 case 'f': 1288 c = '\f'; 1289 break; 1290 case 'n': 1291 c = '\n'; 1292 break; 1293 case 'r': 1294 c = '\r'; 1295 break; 1296 case 't': 1297 c = '\t'; 1298 break; 1299 case 'v': 1300 c = '\v'; 1301 break; 1302 case 'x': 1303 c = 0; 1304 if (!isxdigit(*str)) 1305 break; 1306 if (isdigit(*str)) 1307 c = *str++ - '0'; 1308 else if (isupper(*str)) 1309 c = *str++ - 'A' + 10; 1310 else 1311 c = *str++ - 'a' + 10; 1312 if (!isxdigit(*str)) 1313 break; 1314 if (isdigit(*str)) 1315 c += *str++ - '0'; 1316 else if (isupper(*str)) 1317 c += *str++ - 'A' + 10; 1318 else 1319 c += *str++ - 'a' + 10; 1320 break; 1321 case '0': case '1': case '2': 1322 case '3': case '4': case '5': 1323 case '6': case '7': 1324 c = *str++ - '0'; 1325 if (*str < '0' || *str > '7') 1326 break; 1327 c = *str++ - '0'; 1328 if (*str < '0' || *str > '7') 1329 break; 1330 c = *str++ - '0'; 1331 break; 1332 default: 1333 break; 1334 } 1335 } 1336 STUFFC(c); 1337 } 1338 } else { 1339 while (*str != '\0') { 1340 oct = strtoul(str, &end, 16); 1341 str = end; 1342 if (oct > 0xff) { 1343 free(octs); 1344 return (-1); 1345 } 1346 STUFFC(oct); 1347 if (*str == ':') 1348 str++; 1349 else if(*str != '\0') { 1350 free(octs); 1351 return (-1); 1352 } 1353 } 1354 } 1355 v->octetstring.octets = octs; 1356 v->octetstring.len = len; 1357 return (0); 1358 # undef STUFFC 1359 } 1360 1361 case SNMP_SYNTAX_OID: 1362 { 1363 u_long subid; 1364 1365 v->oid.len = 0; 1366 1367 for (;;) { 1368 if (v->oid.len == ASN_MAXOIDLEN) 1369 return (-1); 1370 subid = strtoul(str, &end, 10); 1371 str = end; 1372 if (subid > ASN_MAXID) 1373 return (-1); 1374 v->oid.subs[v->oid.len++] = (asn_subid_t)subid; 1375 if (*str == '\0') 1376 break; 1377 if (*str != '.') 1378 return (-1); 1379 str++; 1380 } 1381 return (0); 1382 } 1383 1384 case SNMP_SYNTAX_IPADDRESS: 1385 { 1386 struct hostent *he; 1387 u_long ip[4]; 1388 int n; 1389 1390 if (sscanf(str, "%lu.%lu.%lu.%lu%n", &ip[0], &ip[1], &ip[2], 1391 &ip[3], &n) == 4 && (size_t)n == strlen(str) && 1392 ip[0] <= 0xff && ip[1] <= 0xff && 1393 ip[2] <= 0xff && ip[3] <= 0xff) { 1394 v->ipaddress[0] = (u_char)ip[0]; 1395 v->ipaddress[1] = (u_char)ip[1]; 1396 v->ipaddress[2] = (u_char)ip[2]; 1397 v->ipaddress[3] = (u_char)ip[3]; 1398 return (0); 1399 } 1400 1401 if ((he = gethostbyname(str)) == NULL) 1402 return (-1); 1403 if (he->h_addrtype != AF_INET) 1404 return (-1); 1405 1406 v->ipaddress[0] = he->h_addr[0]; 1407 v->ipaddress[1] = he->h_addr[1]; 1408 v->ipaddress[2] = he->h_addr[2]; 1409 v->ipaddress[3] = he->h_addr[3]; 1410 return (0); 1411 } 1412 1413 case SNMP_SYNTAX_COUNTER: 1414 case SNMP_SYNTAX_GAUGE: 1415 case SNMP_SYNTAX_TIMETICKS: 1416 { 1417 uint64_t sub; 1418 1419 sub = strtoull(str, &end, 0); 1420 if (*end != '\0' || sub > 0xffffffff) 1421 return (-1); 1422 v->uint32 = (uint32_t)sub; 1423 return (0); 1424 } 1425 1426 case SNMP_SYNTAX_COUNTER64: 1427 v->counter64 = strtoull(str, &end, 0); 1428 if (*end != '\0') 1429 return (-1); 1430 return (0); 1431 } 1432 abort(); 1433 } 1434 1435 static void 1436 snmp_error_func(const char *fmt, ...) 1437 { 1438 va_list ap; 1439 1440 va_start(ap, fmt); 1441 fprintf(stderr, "SNMP: "); 1442 vfprintf(stderr, fmt, ap); 1443 fprintf(stderr, "\n"); 1444 va_end(ap); 1445 } 1446 1447 static void 1448 snmp_printf_func(const char *fmt, ...) 1449 { 1450 va_list ap; 1451 1452 va_start(ap, fmt); 1453 vfprintf(stderr, fmt, ap); 1454 va_end(ap); 1455 } 1456