1 /*- 2 * Copyright (c) 2006 The FreeBSD Project 3 * All rights reserved. 4 * 5 * Author: Shteryana Shopova <syrinx@FreeBSD.org> 6 * 7 * Redistribution of this software and documentation and use in source and 8 * binary forms, with or without modification, are permitted provided that 9 * the following conditions are met: 10 * 11 * 1. Redistributions of source code or documentation must retain the above 12 * copyright notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * Textual conventions for OctetStrings 30 * 31 * $FreeBSD$ 32 */ 33 34 #include <sys/param.h> 35 #include <sys/queue.h> 36 #include <sys/socket.h> 37 #include <sys/uio.h> 38 39 #include <ctype.h> 40 #include <err.h> 41 #include <errno.h> 42 #include <fcntl.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <syslog.h> 47 #include <unistd.h> 48 49 #include <arpa/inet.h> 50 #include <netinet/in.h> 51 52 #include <bsnmp/asn1.h> 53 #include <bsnmp/snmp.h> 54 #include "bsnmptc.h" 55 #include "bsnmptools.h" 56 57 /* OctetString, DisplayString */ 58 static char *snmp_oct2str(uint32_t, char *, char *); 59 static char *snmp_str2asn_oid(char *, struct asn_oid *); 60 static int parse_octetstring(struct snmp_value *, char *); 61 62 /* DateAndTime */ 63 static char *snmp_octstr2date(uint32_t, char *, char *); 64 static char *snmp_date2asn_oid(char * , struct asn_oid *); 65 static int parse_dateandtime(struct snmp_value *, char *); 66 67 /* PhysAddress */ 68 static char *snmp_oct2physAddr(uint32_t, char *, char *); 69 static char *snmp_addr2asn_oid(char *, struct asn_oid *); 70 static int parse_physaddress(struct snmp_value *, char *); 71 72 /* NTPTimeStamp */ 73 static char *snmp_oct2ntp_ts(uint32_t, char *, char *); 74 static char *snmp_ntp_ts2asn_oid(char *, struct asn_oid *); 75 static int parse_ntp_ts(struct snmp_value *, char *); 76 77 /* BridgeId */ 78 static char *snmp_oct2bridgeid(uint32_t, char *, char *); 79 static char *snmp_bridgeid2oct(char *, struct asn_oid *); 80 static int parse_bridge_id(struct snmp_value *, char *); 81 82 /* BridgePortId */ 83 static char *snmp_oct2bport_id(uint32_t, char *, char *); 84 static char *snmp_bport_id2oct(char *, struct asn_oid *); 85 static int parse_bport_id(struct snmp_value *, char *); 86 87 /* InetAddress */ 88 static char *snmp_oct2inetaddr(uint32_t len, char *octets, char *buf); 89 static char *snmp_inetaddr2oct(char *str, struct asn_oid *oid); 90 static int32_t parse_inetaddr(struct snmp_value *value, char *string); 91 92 static char *snmp_oct2bits(uint32_t len, char *octets, char *buf); 93 static char *snmp_bits2oct(char *str, struct asn_oid *oid); 94 static int32_t parse_bits(struct snmp_value *value, char *string); 95 96 struct snmp_text_conv { 97 enum snmp_tc tc; 98 const char *tc_str; 99 int32_t len; 100 snmp_oct2tc_f oct2tc; 101 snmp_tc2oid_f tc2oid; 102 snmp_tc2oct_f tc2oct; 103 } text_convs[] = { 104 { SNMP_STRING, "OctetString", SNMP_VAR_STRSZ, 105 snmp_oct2str, snmp_str2asn_oid, parse_octetstring }, 106 107 { SNMP_DISPLAYSTRING, "DisplayString" , SNMP_VAR_STRSZ, 108 snmp_oct2str, snmp_str2asn_oid, parse_octetstring }, 109 110 { SNMP_DATEANDTIME, "DateAndTime", SNMP_DATETIME_STRSZ, 111 snmp_octstr2date, snmp_date2asn_oid, parse_dateandtime }, 112 113 { SNMP_PHYSADDR, "PhysAddress", SNMP_PHYSADDR_STRSZ, 114 snmp_oct2physAddr, snmp_addr2asn_oid, parse_physaddress }, 115 116 { SNMP_ATMESI, "AtmESI", SNMP_PHYSADDR_STRSZ, 117 snmp_oct2physAddr, snmp_addr2asn_oid, parse_physaddress }, 118 119 { SNMP_NTP_TIMESTAMP, "NTPTimeStamp", SNMP_NTP_TS_STRSZ, 120 snmp_oct2ntp_ts, snmp_ntp_ts2asn_oid, parse_ntp_ts }, 121 122 { SNMP_MACADDRESS, "MacAddress", SNMP_PHYSADDR_STRSZ, 123 snmp_oct2physAddr, snmp_addr2asn_oid, parse_physaddress }, 124 125 { SNMP_BRIDGE_ID, "BridgeId", SNMP_BRIDGEID_STRSZ, 126 snmp_oct2bridgeid, snmp_bridgeid2oct, parse_bridge_id }, 127 128 { SNMP_BPORT_ID, "BridgePortId", SNMP_BPORT_STRSZ, 129 snmp_oct2bport_id, snmp_bport_id2oct, parse_bport_id }, 130 131 { SNMP_INETADDRESS, "InetAddress", SNMP_INADDRS_STRSZ, 132 snmp_oct2inetaddr, snmp_inetaddr2oct, parse_inetaddr }, 133 134 { SNMP_TC_OWN, "BITS", SNMP_VAR_STRSZ, 135 snmp_oct2bits, snmp_bits2oct, parse_bits }, 136 137 { SNMP_UNKNOWN, "Unknown", SNMP_VAR_STRSZ, snmp_oct2str, 138 snmp_str2asn_oid, parse_octetstring } /* keep last */ 139 }; 140 141 /* Common API */ 142 enum snmp_tc 143 snmp_get_tc(char *str) 144 { 145 int i; 146 for (i = 0; i < SNMP_UNKNOWN; i++) { 147 if (!strncmp(text_convs[i].tc_str, str, 148 strlen(text_convs[i].tc_str))) 149 return (text_convs[i].tc); 150 } 151 152 return (SNMP_STRING); 153 } 154 155 char * 156 snmp_oct2tc(enum snmp_tc tc, uint32_t len, char *octets) 157 { 158 uint32_t tc_len; 159 char * buf; 160 161 if (tc < 0 || tc > SNMP_UNKNOWN) 162 tc = SNMP_UNKNOWN; 163 164 if (text_convs[tc].len > 0) 165 tc_len = text_convs[tc].len; 166 else 167 tc_len = 2 * len + 3; 168 169 if ((buf = malloc(tc_len)) == NULL ) { 170 syslog(LOG_ERR, "malloc failed - %s", strerror(errno)); 171 return (NULL); 172 } 173 174 memset(buf, 0, tc_len); 175 if (text_convs[tc].oct2tc(len, octets, buf) == NULL) { 176 free(buf); 177 return (NULL); 178 } 179 180 return (buf); 181 } 182 183 char * 184 snmp_tc2oid(enum snmp_tc tc, char *str, struct asn_oid *oid) 185 { 186 if (tc < 0 || tc > SNMP_UNKNOWN) 187 tc = SNMP_UNKNOWN; 188 189 return (text_convs[tc].tc2oid(str, oid)); 190 } 191 192 int32_t 193 snmp_tc2oct(enum snmp_tc tc, struct snmp_value *value, char *string) 194 { 195 if (tc < 0 || tc > SNMP_UNKNOWN) 196 tc = SNMP_UNKNOWN; 197 198 return (text_convs[tc].tc2oct(value, string)); 199 } 200 201 /***************************************************** 202 * Basic OctetString type. 203 */ 204 static char * 205 snmp_oct2str(uint32_t len, char *octets, char *buf) 206 { 207 uint8_t binary = 0; 208 uint32_t i; 209 char *ptr; 210 211 if (len > MAX_OCTSTRING_LEN || octets == NULL || buf == NULL) 212 return (NULL); 213 214 for (ptr = buf, i = 0; i < len; i++) 215 if (!isprint(octets[i])) { 216 binary = 1; 217 buf += sprintf(buf, "0x"); 218 break; 219 } 220 221 for (ptr = buf, i = 0; i < len; i++) 222 if (!binary) 223 ptr += sprintf(ptr, "%c", octets[i]); 224 else 225 ptr += sprintf(ptr, "%2.2x", (u_char)octets[i]); 226 227 return (buf); 228 } 229 230 static char * 231 snmp_str2asn_oid(char *str, struct asn_oid *oid) 232 { 233 uint32_t i, len = 0; 234 235 /* 236 * OctetStrings are allowed max length of ASN_MAXOCTETSTRING, 237 * but trying to index an entry with such a long OctetString 238 * will fail anyway. 239 */ 240 for (len = 0; len < ASN_MAXOIDLEN; len++) { 241 if (strchr(",]", *(str + len)) != NULL) 242 break; 243 } 244 245 if (len >= ASN_MAXOIDLEN) 246 return (NULL); 247 248 if (snmp_suboid_append(oid, (asn_subid_t) len) < 0) 249 return (NULL); 250 251 for (i = 0; i < len; i++) 252 if (snmp_suboid_append(oid, (asn_subid_t) *(str + i)) < 0) 253 return (NULL); 254 255 return (str + len); 256 } 257 258 static int32_t 259 parse_octetstring(struct snmp_value *value, char *val) 260 { 261 size_t len; 262 263 if ((len = strlen(val)) >= MAX_OCTSTRING_LEN) { 264 warnx("Octetstring too long - %d is max allowed", 265 MAX_OCTSTRING_LEN - 1); 266 return (-1); 267 } 268 269 value->v.octetstring.len = len; 270 271 if((value->v.octetstring.octets = malloc(len)) == NULL) { 272 syslog(LOG_ERR,"malloc failed: %s", strerror(errno)); 273 return (-1); 274 } 275 276 memcpy(value->v.octetstring.octets, val, len); 277 value->syntax = SNMP_SYNTAX_OCTETSTRING; 278 279 return (0); 280 } 281 282 /************************************************************* 283 * DateAndTime 284 ************************************************************* 285 * rfc 2579 specification: 286 * DateAndTime ::= TEXTUAL-CONVENTION 287 * DISPLAY-HINT "2d-1d-1d,1d:1d:1d.1d,1a1d:1d" 288 * STATUS current 289 * DESCRIPTION 290 * "A date-time specification. 291 * 292 * field octets contents range 293 * ----- ------ -------- ----- 294 * 1 1-2 year* 0..65536 295 * 2 3 month 1..12 296 * 3 4 day 1..31 297 * 4 5 hour 0..23 298 * 5 6 minutes 0..59 299 * 6 7 seconds 0..60 300 * (use 60 for leap-second) 301 * 7 8 deci-seconds 0..9 302 * 8 9 direction from UTC '+' / '-' 303 * 9 10 hours from UTC* 0..13 304 * 10 11 minutes from UTC 0..59 305 * 306 * * Notes: 307 * - the value of year is in network-byte order 308 * - daylight saving time in New Zealand is +13 309 * 310 * For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be 311 * displayed as: 312 * 313 * 1992-5-26,13:30:15.0,-4:0 314 */ 315 static char * 316 snmp_octstr2date(uint32_t len, char *octets, char *buf) 317 { 318 int year; 319 char *ptr; 320 321 if (len != SNMP_DATETIME_OCTETS || octets == NULL || buf == NULL) 322 return (NULL); 323 324 buf[0]= '\0'; 325 year = (octets[0] << 8); 326 year += (octets[1]); 327 328 ptr = buf; 329 ptr += sprintf(ptr, "%4.4d-%.2d-%.2d, ", year, octets[2],octets[3]); 330 ptr += sprintf(ptr, "%2.2d:%2.2d:%2.2d.%.2d, ", octets[4],octets[5], 331 octets[6],octets[7]); 332 ptr += sprintf(ptr, "%c%.2d:%.2d", octets[8],octets[9],octets[10]); 333 334 return (buf); 335 } 336 337 static char * 338 snmp_date2asn_oid(char *str, struct asn_oid *oid) 339 { 340 char *endptr, *ptr; 341 static const char UTC[3] = "UTC"; 342 int32_t saved_errno; 343 uint32_t v; 344 345 if (snmp_suboid_append(oid, (asn_subid_t) SNMP_DATETIME_OCTETS) < 0) 346 return (NULL); 347 348 /* Read 'YYYY-' and write it in two subs. */ 349 ptr = str; 350 saved_errno = errno; 351 errno = 0; 352 v = strtoul(ptr, &endptr, 10); 353 if (v > 0xffff) 354 goto error; 355 else 356 errno = saved_errno; 357 if (*endptr != '-') 358 goto error1; 359 if (snmp_suboid_append(oid, (asn_subid_t) ((v & 0xff00) >> 8)) < 0) 360 return (NULL); 361 if (snmp_suboid_append(oid, (asn_subid_t) (v & 0xff)) < 0) 362 return (NULL); 363 364 /* 'MM-' */ 365 ptr = endptr + 1; 366 saved_errno = errno; 367 v = strtoul(ptr, &endptr, 10); 368 if (errno != 0) 369 goto error; 370 else 371 errno = saved_errno; 372 if (*endptr != '-') 373 goto error1; 374 if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 375 return (NULL); 376 377 /* 'DD,' */ 378 ptr = endptr + 1; 379 saved_errno = errno; 380 v = strtoul(ptr, &endptr, 10); 381 if (errno != 0) 382 goto error; 383 else 384 errno = saved_errno; 385 if (*endptr != '-') 386 goto error1; 387 if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 388 return (NULL); 389 390 /* 'HH:' */ 391 ptr = endptr + 1; 392 saved_errno = errno; 393 v = strtoul(ptr, &endptr, 10); 394 if (errno != 0) 395 goto error; 396 else 397 errno = saved_errno; 398 if (*endptr != ':') 399 goto error1; 400 if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 401 return (NULL); 402 403 /* 'MM:' */ 404 ptr = endptr + 1; 405 saved_errno = errno; 406 v = strtoul(ptr, &endptr, 10); 407 if (errno != 0) 408 goto error; 409 else 410 errno = saved_errno; 411 if (*endptr != ':') 412 goto error1; 413 if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 414 return (NULL); 415 416 /* 'SS.' */ 417 ptr = endptr + 1; 418 saved_errno = errno; 419 v = strtoul(ptr, &endptr, 10); 420 if (errno != 0) 421 goto error; 422 else 423 errno = saved_errno; 424 if (*endptr != '.') 425 goto error1; 426 if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 427 return (NULL); 428 429 /* 'M(mseconds),' */ 430 ptr = endptr + 1; 431 saved_errno = errno; 432 v = strtoul(ptr, &endptr, 10); 433 if (errno != 0) 434 goto error; 435 else 436 errno = saved_errno; 437 if (*endptr != ',') 438 goto error1; 439 if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 440 return (NULL); 441 442 /* 'UTC' - optional */ 443 ptr = endptr + 1; 444 if (strncmp(ptr, UTC, sizeof(UTC)) == 0) 445 ptr += sizeof(UTC); 446 447 /* '+/-' */ 448 if (*ptr == '-' || *ptr == '+') { 449 if (snmp_suboid_append(oid, (asn_subid_t) (*ptr)) < 0) 450 return (NULL); 451 } else 452 goto error1; 453 454 /* 'HH:' */ 455 ptr = endptr + 1; 456 saved_errno = errno; 457 v = strtoul(ptr, &endptr, 10); 458 if (errno != 0) 459 goto error; 460 else 461 errno = saved_errno; 462 if (*endptr != ':') 463 goto error1; 464 if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 465 return (NULL); 466 467 /* 'MM' - last one - ignore endptr here. */ 468 ptr = endptr + 1; 469 saved_errno = errno; 470 v = strtoul(ptr, &endptr, 10); 471 if (errno != 0) 472 goto error; 473 else 474 errno = saved_errno; 475 if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 476 return (NULL); 477 478 return (endptr); 479 480 error: 481 errno = saved_errno; 482 error1: 483 warnx("Date value %s not supported", str); 484 return (NULL); 485 } 486 487 /* Read a DateAndTime string eg. 1992-5-26,13:30:15.0,-4:0. */ 488 static int32_t 489 parse_dateandtime(struct snmp_value *sv, char *val) 490 { 491 char *endptr; 492 uint32_t v; 493 uint8_t date[SNMP_DATETIME_OCTETS]; 494 495 /* 'YYYY-' */ 496 v = strtoul(val, &endptr, 10); 497 if (v > 0xffff || *endptr != '-') 498 goto error; 499 date[0] = ((v & 0xff00) >> 8); 500 date[1] = (v & 0xff); 501 val = endptr + 1; 502 503 /* 'MM-' */ 504 v = strtoul(val, &endptr, 10); 505 if (v == 0 || v > 12 || *endptr != '-') 506 goto error; 507 date[2] = v; 508 val = endptr + 1; 509 510 /* 'DD,' */ 511 v = strtoul(val, &endptr, 10); 512 if (v == 0 || v > 31 || *endptr != ',') 513 goto error; 514 date[3] = v; 515 val = endptr + 1; 516 517 /* 'HH:' */ 518 v = strtoul(val, &endptr, 10); 519 if (v > 23 || *endptr != ':') 520 goto error; 521 date[4] = v; 522 val = endptr + 1; 523 524 /* 'MM:' */ 525 v = strtoul(val, &endptr, 10); 526 if (v > 59 || *endptr != ':') 527 goto error; 528 date[5] = v; 529 val = endptr + 1; 530 531 /* 'SS.' */ 532 v = strtoul(val, &endptr, 10); 533 if (v > 60 || *endptr != '.') 534 goto error; 535 date[6] = v; 536 val = endptr + 1; 537 538 /* '(deci-)s,' */ 539 v = strtoul(val, &endptr, 10); 540 if (v > 9 || *endptr != ',') 541 goto error; 542 date[7] = v; 543 val = endptr + 1; 544 545 /* offset - '+/-' */ 546 if (*val != '-' && *val != '+') 547 goto error; 548 date[8] = (uint8_t) *val; 549 val = endptr + 1; 550 551 /* 'HH:' - offset from UTC */ 552 v = strtoul(val, &endptr, 10); 553 if (v > 13 || *endptr != ':') 554 goto error; 555 date[9] = v; 556 val = endptr + 1; 557 558 /* 'MM'\0'' offset from UTC */ 559 v = strtoul(val, &endptr, 10); 560 if (v > 59 || *endptr != '\0') 561 goto error; 562 date[10] = v; 563 564 if ((sv->v.octetstring.octets = malloc(SNMP_DATETIME_OCTETS)) == NULL) { 565 warnx("malloc() failed - %s", strerror(errno)); 566 return (-1); 567 } 568 569 sv->v.octetstring.len = SNMP_DATETIME_OCTETS; 570 memcpy(sv->v.octetstring.octets, date, SNMP_DATETIME_OCTETS); 571 sv->syntax = SNMP_SYNTAX_OCTETSTRING; 572 return (1); 573 574 error: 575 warnx("Date value %s not supported", val); 576 return (-1); 577 } 578 579 /************************************************************** 580 * PhysAddress 581 */ 582 static char * 583 snmp_oct2physAddr(uint32_t len, char *octets, char *buf) 584 { 585 char *ptr; 586 uint32_t i; 587 588 if (len != SNMP_PHYSADDR_OCTETS || octets == NULL || buf == NULL) 589 return (NULL); 590 591 buf[0]= '\0'; 592 593 ptr = buf; 594 ptr += sprintf(ptr, "%2.2x", octets[0]); 595 for (i = 1; i < 6; i++) 596 ptr += sprintf(ptr, ":%2.2x", octets[i]); 597 598 return (buf); 599 } 600 601 static char * 602 snmp_addr2asn_oid(char *str, struct asn_oid *oid) 603 { 604 char *endptr, *ptr; 605 uint32_t v, i; 606 int saved_errno; 607 608 if (snmp_suboid_append(oid, (asn_subid_t) SNMP_PHYSADDR_OCTETS) < 0) 609 return (NULL); 610 611 ptr = str; 612 for (i = 0; i < 5; i++) { 613 saved_errno = errno; 614 v = strtoul(ptr, &endptr, 16); 615 errno = saved_errno; 616 if (v > 0xff) { 617 warnx("Integer value %s not supported", str); 618 return (NULL); 619 } 620 if (*endptr != ':') { 621 warnx("Failed adding oid - %s",str); 622 return (NULL); 623 } 624 if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 625 return (NULL); 626 ptr = endptr + 1; 627 } 628 629 /* The last one - don't check the ending char here. */ 630 saved_errno = errno; 631 v = strtoul(ptr, &endptr, 16); 632 errno = saved_errno; 633 if (v > 0xff) { 634 warnx("Integer value %s not supported", str); 635 return (NULL); 636 } 637 if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 638 return (NULL); 639 640 return (endptr); 641 } 642 643 static int32_t 644 parse_physaddress(struct snmp_value *sv, char *val) 645 { 646 char *endptr; 647 int32_t i; 648 uint32_t v; 649 uint8_t phys_addr[SNMP_PHYSADDR_OCTETS]; 650 651 for (i = 0; i < 5; i++) { 652 v = strtoul(val, &endptr, 16); 653 if (v > 0xff) { 654 warnx("Integer value %s not supported", val); 655 return (-1); 656 } 657 if(*endptr != ':') { 658 warnx("Failed reading octet - %s", val); 659 return (-1); 660 } 661 phys_addr[i] = v; 662 val = endptr + 1; 663 } 664 665 /* The last one - don't check the ending char here. */ 666 v = strtoul(val, &endptr, 16); 667 if (v > 0xff) { 668 warnx("Integer value %s not supported", val); 669 return (-1); 670 } 671 phys_addr[5] = v; 672 673 if ((sv->v.octetstring.octets = malloc(SNMP_PHYSADDR_OCTETS)) == NULL) { 674 syslog(LOG_ERR,"malloc failed: %s", strerror(errno)); 675 return (-1); 676 } 677 678 sv->v.octetstring.len = SNMP_PHYSADDR_OCTETS; 679 memcpy(sv->v.octetstring.octets, phys_addr, SNMP_PHYSADDR_OCTETS); 680 sv->syntax = SNMP_SYNTAX_OCTETSTRING; 681 return (1); 682 } 683 684 /************************************************************** 685 * NTPTimeStamp 686 ************************************************************** 687 * NTP MIB, Revision 0.2, 7/25/97: 688 * NTPTimeStamp ::= TEXTUAL-CONVENTION 689 * DISPLAY-HINT "4x.4x" 690 * STATUS current 691 * DESCRIPTION 692 * "" 693 * SYNTAX OCTET STRING (SIZE(8)) 694 */ 695 static char * 696 snmp_oct2ntp_ts(uint32_t len, char *octets, char *buf) 697 { 698 char *ptr; 699 uint32_t i; 700 701 if (len != SNMP_NTP_TS_OCTETS || octets == NULL || buf == NULL) 702 return (NULL); 703 704 buf[0]= '\0'; 705 706 ptr = buf; 707 i = octets[0] * 1000 + octets[1] * 100 + octets[2] * 10 + octets[3]; 708 ptr += sprintf(ptr, "%4.4d", i); 709 i = octets[4] * 1000 + octets[5] * 100 + octets[6] * 10 + octets[7]; 710 ptr += sprintf(ptr, ".%4.4d", i); 711 712 return (buf); 713 } 714 715 static char * 716 snmp_ntp_ts2asn_oid(char *str, struct asn_oid *oid) 717 { 718 char *endptr, *ptr; 719 uint32_t v, i, d; 720 struct asn_oid suboid; 721 int saved_errno; 722 723 if (snmp_suboid_append(oid, (asn_subid_t) SNMP_NTP_TS_OCTETS) < 0) 724 return (NULL); 725 726 ptr = str; 727 saved_errno = errno; 728 v = strtoul(ptr, &endptr, 10); 729 if (errno != 0 || (v / 1000) > 9) { 730 warnx("Integer value %s not supported", str); 731 errno = saved_errno; 732 return (NULL); 733 } else 734 errno = saved_errno; 735 736 if (*endptr != '.') { 737 warnx("Failed adding oid - %s",str); 738 return (NULL); 739 } 740 741 memset(&suboid, 0, sizeof(struct asn_oid)); 742 suboid.len = SNMP_NTP_TS_OCTETS; 743 744 for (i = 0, d = 1000; i < 4; i++) { 745 suboid.subs[i] = v / d; 746 v = v % d; 747 d = d / 10; 748 } 749 750 ptr = endptr + 1; 751 saved_errno = errno; 752 v = strtoul(ptr, &endptr, 10); 753 if (errno != 0 || (v / 1000) > 9) { 754 warnx("Integer value %s not supported", str); 755 errno = saved_errno; 756 return (NULL); 757 } else 758 errno = saved_errno; 759 760 for (i = 0, d = 1000; i < 4; i++) { 761 suboid.subs[i + 4] = v / d; 762 v = v % d; 763 d = d / 10; 764 } 765 766 asn_append_oid(oid, &suboid); 767 return (endptr); 768 } 769 770 static int32_t 771 parse_ntp_ts(struct snmp_value *sv, char *val) 772 { 773 char *endptr; 774 int32_t i, d, saved_errno; 775 uint32_t v; 776 uint8_t ntp_ts[SNMP_NTP_TS_OCTETS]; 777 778 saved_errno = errno; 779 v = strtoul(val, &endptr, 10); 780 if (errno != 0 || (v / 1000) > 9) { 781 saved_errno = errno; 782 warnx("Integer value %s not supported", val); 783 return (-1); 784 } else 785 saved_errno = errno; 786 787 if (*endptr != '.') { 788 warnx("Failed reading octet - %s", val); 789 return (-1); 790 } 791 792 for (i = 0, d = 1000; i < 4; i++) { 793 ntp_ts[i] = v / d; 794 v = v % d; 795 d = d / 10; 796 } 797 val = endptr + 1; 798 799 saved_errno = errno; 800 v = strtoul(val, &endptr, 10); 801 if (errno != 0 || (v / 1000) > 9) { 802 saved_errno = errno; 803 warnx("Integer value %s not supported", val); 804 return (-1); 805 } else 806 saved_errno = errno; 807 808 for (i = 0, d = 1000; i < 4; i++) { 809 ntp_ts[i + 4] = v / d; 810 v = v % d; 811 d = d / 10; 812 } 813 814 if ((sv->v.octetstring.octets = malloc(SNMP_NTP_TS_OCTETS)) == NULL) { 815 syslog(LOG_ERR,"malloc failed: %s", strerror(errno)); 816 return (-1); 817 } 818 819 sv->v.octetstring.len = SNMP_NTP_TS_OCTETS; 820 memcpy(sv->v.octetstring.octets, ntp_ts, SNMP_NTP_TS_OCTETS); 821 sv->syntax = SNMP_SYNTAX_OCTETSTRING; 822 return (1); 823 } 824 825 /************************************************************** 826 * BridgeId 827 ************************************************************** 828 * BRIDGE-MIB, REVISION "200509190000Z" 829 * BridgeId ::= TEXTUAL-CONVENTION 830 * STATUS current 831 * DESCRIPTION 832 * "The Bridge-Identifier, as used in the Spanning Tree 833 * Protocol, to uniquely identify a bridge. Its first two 834 * octets (in network byte order) contain a priority value, 835 * and its last 6 octets contain the MAC address used to 836 * refer to a bridge in a unique fashion (typically, the 837 * numerically smallest MAC address of all ports on the 838 * bridge)." 839 * SYNTAX OCTET STRING (SIZE (8)) 840 */ 841 static char * 842 snmp_oct2bridgeid(uint32_t len, char *octets, char *buf) 843 { 844 char *ptr; 845 uint32_t i, priority; 846 847 if (len != SNMP_BRIDGEID_OCTETS || octets == NULL || buf == NULL) 848 return (NULL); 849 850 buf[0]= '\0'; 851 ptr = buf; 852 853 priority = octets[0] << 8; 854 priority += octets[1]; 855 if (priority > SNMP_MAX_BRIDGE_PRIORITY) { 856 warnx("Invalid bridge priority %d", priority); 857 return (NULL); 858 } else 859 ptr += sprintf(ptr, "%d.", octets[0]); 860 861 ptr += sprintf(ptr, "%2.2x", octets[2]); 862 863 for (i = 1; i < 6; i++) 864 ptr += sprintf(ptr, ":%2.2x", octets[i + 2]); 865 866 return (buf); 867 } 868 869 static char * 870 snmp_bridgeid2oct(char *str, struct asn_oid *oid) 871 { 872 char *endptr, *ptr; 873 uint32_t v, i; 874 int32_t saved_errno; 875 876 if (snmp_suboid_append(oid, (asn_subid_t) SNMP_BRIDGEID_OCTETS) < 0) 877 return (NULL); 878 879 ptr = str; 880 /* Read the priority. */ 881 saved_errno = errno; 882 v = strtoul(ptr, &endptr, 10); 883 errno = 0; 884 885 if (v > SNMP_MAX_BRIDGE_PRIORITY || errno != 0 || *endptr != '.') { 886 errno = saved_errno; 887 warnx("Bad bridge priority value %d", v); 888 return (NULL); 889 } 890 891 if (snmp_suboid_append(oid, (asn_subid_t) (v & 0xff00)) < 0) 892 return (NULL); 893 894 if (snmp_suboid_append(oid, (asn_subid_t) (v & 0xff)) < 0) 895 return (NULL); 896 897 ptr = endptr + 1; 898 for (i = 0; i < 5; i++) { 899 saved_errno = errno; 900 v = strtoul(ptr, &endptr, 16); 901 errno = saved_errno; 902 if (v > 0xff) { 903 warnx("Integer value %s not supported", str); 904 return (NULL); 905 } 906 if (*endptr != ':') { 907 warnx("Failed adding oid - %s",str); 908 return (NULL); 909 } 910 if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 911 return (NULL); 912 ptr = endptr + 1; 913 } 914 915 /* The last one - don't check the ending char here. */ 916 saved_errno = errno; 917 v = strtoul(ptr, &endptr, 16); 918 errno = saved_errno; 919 if (v > 0xff) { 920 warnx("Integer value %s not supported", str); 921 return (NULL); 922 } 923 if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 924 return (NULL); 925 926 return (endptr); 927 } 928 929 static int32_t 930 parse_bridge_id(struct snmp_value *sv, char *string) 931 { 932 char *ptr, *endptr; 933 int32_t i, saved_errno; 934 uint32_t v; 935 uint8_t bridge_id[SNMP_BRIDGEID_OCTETS]; 936 937 ptr = string; 938 /* Read the priority. */ 939 saved_errno = errno; 940 errno = 0; 941 v = strtoul(string, &endptr, 10); 942 errno = saved_errno; 943 944 if (v > SNMP_MAX_BRIDGE_PRIORITY || errno != 0 || *endptr != '.') { 945 errno = saved_errno; 946 warnx("Bad bridge priority value %d", v); 947 return (-1); 948 } 949 950 bridge_id[0] = (v & 0xff00); 951 bridge_id[1] = (v & 0xff); 952 953 string = endptr + 1; 954 955 for (i = 0; i < 5; i++) { 956 v = strtoul(string, &endptr, 16); 957 if (v > 0xff) { 958 warnx("Integer value %s not supported", string); 959 return (-1); 960 } 961 if(*endptr != ':') { 962 warnx("Failed reading octet - %s", string); 963 return (-1); 964 } 965 bridge_id[i + 2] = v; 966 string = endptr + 1; 967 } 968 969 /* The last one - don't check the ending char here. */ 970 v = strtoul(string, &endptr, 16); 971 if (v > 0xff) { 972 warnx("Integer value %s not supported", string); 973 return (-1); 974 } 975 bridge_id[7] = v; 976 977 if ((sv->v.octetstring.octets = malloc(SNMP_BRIDGEID_OCTETS)) == NULL) { 978 syslog(LOG_ERR,"malloc failed: %s", strerror(errno)); 979 return (-1); 980 } 981 982 sv->v.octetstring.len = SNMP_BRIDGEID_OCTETS; 983 memcpy(sv->v.octetstring.octets, bridge_id, SNMP_BRIDGEID_OCTETS); 984 sv->syntax = SNMP_SYNTAX_OCTETSTRING; 985 return (1); 986 } 987 988 /************************************************************** 989 * BridgePortId 990 ************************************************************** 991 * BEGEMOT-BRIDGE-MIB, LAST-UPDATED "200608100000Z" 992 * BridgePortId ::= TEXTUAL-CONVENTION 993 * DISPLAY-HINT "1x.1x" 994 * STATUS current 995 * DESCRIPTION 996 * "A port identifier that contains a bridge port's STP priority 997 * in the first octet and the port number in the second octet." 998 * SYNTAX OCTET STRING (SIZE(2)) 999 */ 1000 static char * 1001 snmp_oct2bport_id(uint32_t len, char *octets, char *buf) 1002 { 1003 char *ptr; 1004 1005 if (len != SNMP_BPORT_OCTETS || octets == NULL || buf == NULL) 1006 return (NULL); 1007 1008 buf[0]= '\0'; 1009 ptr = buf; 1010 1011 ptr += sprintf(ptr, "%d.", octets[0]); 1012 ptr += sprintf(ptr, "%d", octets[1]); 1013 1014 return (buf); 1015 } 1016 1017 static char * 1018 snmp_bport_id2oct(char *str, struct asn_oid *oid) 1019 { 1020 char *endptr, *ptr; 1021 uint32_t v; 1022 int saved_errno; 1023 1024 if (snmp_suboid_append(oid, (asn_subid_t) SNMP_BPORT_OCTETS) < 0) 1025 return (NULL); 1026 1027 ptr = str; 1028 /* Read the priority. */ 1029 saved_errno = errno; 1030 v = strtoul(ptr, &endptr, 10); 1031 errno = 0; 1032 1033 if (v > SNMP_MAX_BPORT_PRIORITY || errno != 0 || *endptr != '.') { 1034 errno = saved_errno; 1035 warnx("Bad bridge port priority value %d", v); 1036 return (NULL); 1037 } 1038 1039 if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 1040 return (NULL); 1041 1042 saved_errno = errno; 1043 v = strtoul(ptr, &endptr, 16); 1044 errno = saved_errno; 1045 1046 if (v > 0xff) { 1047 warnx("Bad port number - %d", v); 1048 return (NULL); 1049 } 1050 1051 if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 1052 return (NULL); 1053 1054 return (endptr); 1055 } 1056 1057 static int32_t 1058 parse_bport_id(struct snmp_value *value, char *string) 1059 { 1060 char *ptr, *endptr; 1061 int saved_errno; 1062 uint32_t v; 1063 uint8_t bport_id[SNMP_BPORT_OCTETS]; 1064 1065 ptr = string; 1066 /* Read the priority. */ 1067 saved_errno = errno; 1068 errno = 0; 1069 v = strtoul(string, &endptr, 10); 1070 errno = saved_errno; 1071 1072 if (v > SNMP_MAX_BPORT_PRIORITY || errno != 0 || *endptr != '.') { 1073 errno = saved_errno; 1074 warnx("Bad bridge port priority value %d", v); 1075 return (-1); 1076 } 1077 1078 bport_id[0] = v; 1079 1080 string = endptr + 1; 1081 v = strtoul(string, &endptr, 16); 1082 if (v > 0xff) { 1083 warnx("Bad port number - %d", v); 1084 return (-1); 1085 } 1086 1087 bport_id[1] = v; 1088 1089 if ((value->v.octetstring.octets = malloc(SNMP_BPORT_OCTETS)) == NULL) { 1090 syslog(LOG_ERR,"malloc failed: %s", strerror(errno)); 1091 return (-1); 1092 } 1093 1094 value->v.octetstring.len = SNMP_BPORT_OCTETS; 1095 memcpy(value->v.octetstring.octets, bport_id, SNMP_BPORT_OCTETS); 1096 value->syntax = SNMP_SYNTAX_OCTETSTRING; 1097 return (1); 1098 } 1099 /************************************************************** 1100 * InetAddress 1101 ************************************************************** 1102 * INET-ADDRESS-MIB, REVISION "200502040000Z" 1103 * InetAddress ::= TEXTUAL-CONVENTION 1104 * STATUS current 1105 * DESCRIPTION 1106 * "Denotes a generic Internet address. 1107 * 1108 * An InetAddress value is always interpreted within the context 1109 * of an InetAddressType value. Every usage of the InetAddress 1110 * textual convention is required to specify the InetAddressType 1111 * object that provides the context. It is suggested that the 1112 * InetAddressType object be logically registered before the 1113 * object(s) that use the InetAddress textual convention, if 1114 * they appear in the same logical row. 1115 * 1116 * The value of an InetAddress object must always be 1117 * consistent with the value of the associated InetAddressType 1118 * object. Attempts to set an InetAddress object to a value 1119 * inconsistent with the associated InetAddressType 1120 * must fail with an inconsistentValue error. 1121 * 1122 * When this textual convention is used as the syntax of an 1123 * index object, there may be issues with the limit of 128 1124 * sub-identifiers specified in SMIv2, STD 58. In this case, 1125 * the object definition MUST include a 'SIZE' clause to 1126 * limit the number of potential instance sub-identifiers; 1127 * otherwise the applicable constraints MUST be stated in 1128 * the appropriate conceptual row DESCRIPTION clauses, or 1129 * in the surrounding documentation if there is no single 1130 * DESCRIPTION clause that is appropriate." 1131 * SYNTAX OCTET STRING (SIZE (0..255)) 1132 ************************************************************** 1133 * TODO: FIXME!!! syrinx: Since we do not support checking the 1134 * consistency of a varbinding based on the value of a previous 1135 * one, try to guess the type of address based on the 1136 * OctetString SIZE - 4 for IPv4, 16 for IPv6, others currently 1137 * not supported. 1138 */ 1139 static char * 1140 snmp_oct2inetaddr(uint32_t len, char *octets, char *buf) 1141 { 1142 int af; 1143 void *ip; 1144 struct in_addr ipv4; 1145 struct in6_addr ipv6; 1146 1147 if (len > MAX_OCTSTRING_LEN || octets == NULL || buf == NULL) 1148 return (NULL); 1149 1150 switch (len) { 1151 /* XXX: FIXME - IPv4*/ 1152 case 4: 1153 memcpy(&ipv4.s_addr, octets, sizeof(ipv4.s_addr)); 1154 af = AF_INET; 1155 ip = &ipv4; 1156 break; 1157 1158 /* XXX: FIXME - IPv4*/ 1159 case 16: 1160 memcpy(ipv6.s6_addr, octets, sizeof(ipv6.s6_addr)); 1161 af = AF_INET6; 1162 ip = &ipv6; 1163 break; 1164 1165 default: 1166 return (NULL); 1167 } 1168 1169 if (inet_ntop(af, ip, buf, SNMP_INADDRS_STRSZ) == NULL) { 1170 warnx("inet_ntop failed - %s", strerror(errno)); 1171 return (NULL); 1172 } 1173 1174 return (buf); 1175 } 1176 1177 static char * 1178 snmp_inetaddr2oct(char *str, struct asn_oid *oid) 1179 { 1180 return (NULL); 1181 } 1182 1183 static int32_t 1184 parse_inetaddr(struct snmp_value *value, char *string) 1185 { 1186 return (-1); 1187 } 1188 1189 /************************************************************** 1190 * SNMP BITS type - XXX: FIXME 1191 **************************************************************/ 1192 static char * 1193 snmp_oct2bits(uint32_t len, char *octets, char *buf) 1194 { 1195 int i, bits; 1196 uint64_t value; 1197 1198 if (len > sizeof(value) || octets == NULL || buf == NULL) 1199 return (NULL); 1200 1201 for (i = len, value = 0, bits = 0; i > 0; i--, bits += 8) 1202 value += octets[i] << bits; 1203 1204 buf[0]= '\0'; 1205 sprintf(buf, "0x%llx.",(long long unsigned) value); 1206 1207 return (buf); 1208 } 1209 1210 static char * 1211 snmp_bits2oct(char *str, struct asn_oid *oid) 1212 { 1213 char *endptr; 1214 int i, size, bits, saved_errno; 1215 uint64_t v, mask = 0xFF00000000000000; 1216 1217 saved_errno = errno; 1218 errno = 0; 1219 1220 v = strtoull(str, &endptr, 16); 1221 if (errno != 0) { 1222 warnx("Bad BITS value %s - %s", str, strerror(errno)); 1223 errno = saved_errno; 1224 return (NULL); 1225 } 1226 1227 bits = 8; 1228 /* Determine length - up to 8 octets supported so far. */ 1229 for (size = sizeof(v); size > 0; size--) { 1230 if ((v & mask) != 0) 1231 break; 1232 mask = mask >> bits; 1233 } 1234 1235 if (size == 0) 1236 size = 1; 1237 1238 if (snmp_suboid_append(oid, (asn_subid_t) size) < 0) 1239 return (NULL); 1240 1241 for (i = 0, bits = 0; i < size; i++, bits += 8) 1242 if (snmp_suboid_append(oid, 1243 (asn_subid_t)((v & mask) >> bits)) < 0) 1244 return (NULL); 1245 1246 return (endptr); 1247 } 1248 1249 static int32_t 1250 parse_bits(struct snmp_value *value, char *string) 1251 { 1252 char *endptr; 1253 int i, size, bits, saved_errno; 1254 uint64_t v, mask = 0xFF00000000000000; 1255 1256 saved_errno = errno; 1257 errno = 0; 1258 1259 v = strtoull(string, &endptr, 16); 1260 1261 if (errno != 0) { 1262 warnx("Bad BITS value %s - %s", string, strerror(errno)); 1263 errno = saved_errno; 1264 return (-1); 1265 } 1266 1267 bits = 8; 1268 /* Determine length - up to 8 octets supported so far. */ 1269 for (size = sizeof(v); size > 0; size--) { 1270 if ((v & mask) != 0) 1271 break; 1272 mask = mask >> bits; 1273 } 1274 1275 if (size == 0) 1276 size = 1; 1277 1278 if ((value->v.octetstring.octets = malloc(size)) == NULL) { 1279 syslog(LOG_ERR, "malloc failed: %s", strerror(errno)); 1280 return (-1); 1281 } 1282 1283 value->v.octetstring.len = size; 1284 for (i = 0, bits = 0; i < size; i++, bits += 8) 1285 value->v.octetstring.octets[i] = (v & mask) >> bits; 1286 value->syntax = SNMP_SYNTAX_OCTETSTRING; 1287 return (1); 1288 } 1289