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