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 * $FreeBSD$ 30 */ 31 32 /* 33 * Read file containing table description - reuse magic from gensnmptree.c. 34 * Hopefully one day most of the code here will be part of libbsnmp and 35 * this duplication won't be necessary. 36 * 37 * Syntax is: 38 * --------- 39 * file := top | top file 40 * 41 * top := tree | typedef | include 42 * 43 * tree := head elements ')' 44 * 45 * entry := head ':' index STRING elements ')' 46 * 47 * leaf := head type STRING ACCESS ')' 48 * 49 * column := head type ACCESS ')' 50 * 51 * type := BASETYPE | BASETYPE '|' subtype | enum | bits 52 * 53 * subtype := STRING 54 * 55 * enum := ENUM '(' value ')' 56 * 57 * bits := BITS '(' value ')' 58 * 59 * value := INT STRING | INT STRING value 60 * 61 * head := '(' INT STRING 62 * 63 * elements := EMPTY | elements element 64 * 65 * element := tree | leaf | column 66 * 67 * index := type | index type 68 * 69 * typedef := 'typedef' STRING type 70 * 71 * include := 'include' filespec 72 * 73 * filespec := '"' STRING '"' | '<' STRING '>' 74 */ 75 76 #include <sys/param.h> 77 #include <sys/queue.h> 78 #include <sys/uio.h> 79 80 #include <ctype.h> 81 #include <err.h> 82 #include <errno.h> 83 #include <fcntl.h> 84 #include <paths.h> 85 #include <stdio.h> 86 #include <stdlib.h> 87 #include <string.h> 88 #include <syslog.h> 89 #include <unistd.h> 90 91 #include <bsnmp/asn1.h> 92 #include <bsnmp/snmp.h> 93 #include <bsnmp/snmpagent.h> /* SNMP_INDEXES_MAX */ 94 #include "bsnmptc.h" 95 #include "bsnmptools.h" 96 97 enum snmp_tbl_entry { 98 ENTRY_NONE = 0, 99 ENTRY_INDEX, 100 ENTRY_DATA 101 }; 102 103 enum { 104 FL_GET = 0x01, 105 FL_SET = 0x02, 106 }; 107 108 /************************************************************ 109 * 110 * Allocate memory and panic just in the case... 111 */ 112 static void * 113 xalloc(size_t size) 114 { 115 void *ptr; 116 117 if ((ptr = malloc(size)) == NULL) 118 err(1, "allocing %zu bytes", size); 119 120 return (ptr); 121 } 122 123 static char * 124 savestr(const char *s) 125 { 126 if (s == NULL) 127 return (NULL); 128 129 return (strcpy(xalloc(strlen(s) + 1), s)); 130 } 131 132 /************************************************************ 133 * 134 * Input stack 135 */ 136 struct input { 137 FILE *fp; 138 uint32_t lno; 139 char *fname; 140 char *path; 141 LIST_ENTRY(input) link; 142 }; 143 144 static LIST_HEAD(, input) inputs = LIST_HEAD_INITIALIZER(inputs); 145 static struct input *input = NULL; 146 static int32_t pbchar = -1; 147 148 #define MAX_PATHS 100 149 150 static const char *paths[MAX_PATHS + 1] = { 151 "/usr/share/snmp/defs", 152 _PATH_LOCALBASE "/share/snmp/defs", 153 NULL 154 }; 155 156 static void 157 input_new(FILE *fp, const char *path, const char *fname) 158 { 159 struct input *ip; 160 161 ip = xalloc(sizeof(*ip)); 162 ip->fp = fp; 163 ip->lno = 1; 164 ip->fname = savestr(fname); 165 ip->path = savestr(path); 166 LIST_INSERT_HEAD(&inputs, ip, link); 167 168 input = ip; 169 } 170 171 static void 172 input_close(void) 173 { 174 if (input == NULL) 175 return; 176 177 fclose(input->fp); 178 free(input->fname); 179 free(input->path); 180 LIST_REMOVE(input, link); 181 free(input); 182 183 input = LIST_FIRST(&inputs); 184 } 185 186 static FILE * 187 tryopen(const char *path, const char *fname) 188 { 189 char *fn; 190 FILE *fp; 191 192 if (path == NULL) 193 fn = savestr(fname); 194 else { 195 fn = xalloc(strlen(path) + strlen(fname) + 2); 196 sprintf(fn, "%s/%s", path, fname); 197 } 198 fp = fopen(fn, "r"); 199 free(fn); 200 return (fp); 201 } 202 203 static int32_t 204 input_fopen(const char *fname) 205 { 206 FILE *fp; 207 u_int p; 208 209 if (fname[0] == '/' || fname[0] == '.' || fname[0] == '~') { 210 if ((fp = tryopen(NULL, fname)) != NULL) { 211 input_new(fp, NULL, fname); 212 return (0); 213 } 214 215 } else { 216 217 for (p = 0; paths[p] != NULL; p++) 218 if ((fp = tryopen(paths[p], fname)) != NULL) { 219 input_new(fp, paths[p], fname); 220 return (0); 221 } 222 } 223 224 warnx("cannot open '%s'", fname); 225 return (-1); 226 } 227 228 static int32_t 229 tgetc(void) 230 { 231 int c; 232 233 if (pbchar != -1) { 234 c = pbchar; 235 pbchar = -1; 236 return (c); 237 } 238 239 for (;;) { 240 if (input == NULL) 241 return (EOF); 242 243 if ((c = getc(input->fp)) != EOF) 244 return (c); 245 246 input_close(); 247 } 248 } 249 250 static int32_t 251 tungetc(int c) 252 { 253 254 if (pbchar != -1) 255 return (-1); 256 257 pbchar = c; 258 return (1); 259 } 260 261 /************************************************************ 262 * 263 * Parsing input 264 */ 265 enum tok { 266 TOK_EOF = 0200, /* end-of-file seen */ 267 TOK_NUM, /* number */ 268 TOK_STR, /* string */ 269 TOK_ACCESS, /* access operator */ 270 TOK_TYPE, /* type operator */ 271 TOK_ENUM, /* enum token (kind of a type) */ 272 TOK_TYPEDEF, /* typedef directive */ 273 TOK_DEFTYPE, /* defined type */ 274 TOK_INCLUDE, /* include directive */ 275 TOK_FILENAME, /* filename ("foo.bar" or <foo.bar>) */ 276 TOK_BITS, /* bits token (kind of a type) */ 277 TOK_ERR /* unexpected char - exit */ 278 }; 279 280 static const struct { 281 const char *str; 282 enum tok tok; 283 uint32_t val; 284 } keywords[] = { 285 { "GET", TOK_ACCESS, FL_GET }, 286 { "SET", TOK_ACCESS, FL_SET }, 287 { "NULL", TOK_TYPE, SNMP_SYNTAX_NULL }, 288 { "INTEGER", TOK_TYPE, SNMP_SYNTAX_INTEGER }, 289 { "INTEGER32", TOK_TYPE, SNMP_SYNTAX_INTEGER }, 290 { "UNSIGNED32", TOK_TYPE, SNMP_SYNTAX_GAUGE }, 291 { "OCTETSTRING", TOK_TYPE, SNMP_SYNTAX_OCTETSTRING }, 292 { "IPADDRESS", TOK_TYPE, SNMP_SYNTAX_IPADDRESS }, 293 { "OID", TOK_TYPE, SNMP_SYNTAX_OID }, 294 { "TIMETICKS", TOK_TYPE, SNMP_SYNTAX_TIMETICKS }, 295 { "COUNTER", TOK_TYPE, SNMP_SYNTAX_COUNTER }, 296 { "GAUGE", TOK_TYPE, SNMP_SYNTAX_GAUGE }, 297 { "COUNTER64", TOK_TYPE, SNMP_SYNTAX_COUNTER64 }, 298 { "ENUM", TOK_ENUM, SNMP_SYNTAX_INTEGER }, 299 { "BITS", TOK_BITS, SNMP_SYNTAX_OCTETSTRING }, 300 { "typedef", TOK_TYPEDEF, 0 }, 301 { "include", TOK_INCLUDE, 0 }, 302 { NULL, 0, 0 } 303 }; 304 305 static struct { 306 /* Current OID type, regarding table membership. */ 307 enum snmp_tbl_entry tbl_type; 308 /* A pointer to a structure in table list to add to its members. */ 309 struct snmp_index_entry *table_idx; 310 } table_data; 311 312 static struct asn_oid current_oid; 313 static char nexttok[MAXSTR]; 314 static u_long val; /* integer values */ 315 static int32_t all_cond; /* all conditions are true */ 316 static int32_t saved_token = -1; 317 318 /* Prepare the global data before parsing a new file. */ 319 static void 320 snmp_import_init(struct asn_oid *append) 321 { 322 memset(&table_data, 0, sizeof(table_data)); 323 memset(¤t_oid, 0, sizeof(struct asn_oid)); 324 memset(nexttok, 0, MAXSTR); 325 326 if (append != NULL) 327 asn_append_oid(¤t_oid, append); 328 329 all_cond = 0; 330 val = 0; 331 saved_token = -1; 332 } 333 334 static int32_t 335 gettoken(struct snmp_toolinfo *snmptoolctx) 336 { 337 int c; 338 struct enum_type *t; 339 340 if (saved_token != -1) { 341 c = saved_token; 342 saved_token = -1; 343 return (c); 344 } 345 346 again: 347 /* 348 * Skip any whitespace before the next token. 349 */ 350 while ((c = tgetc()) != EOF) { 351 if (c == '\n') 352 input->lno++; 353 if (!isspace(c)) 354 break; 355 } 356 if (c == EOF) 357 return (TOK_EOF); 358 359 if (!isascii(c)) { 360 warnx("unexpected character %#2x", (u_int) c); 361 return (TOK_ERR); 362 } 363 364 /* 365 * Skip comments. 366 */ 367 if (c == '#') { 368 while ((c = tgetc()) != EOF) { 369 if (c == '\n') { 370 input->lno++; 371 goto again; 372 } 373 } 374 warnx("unexpected EOF in comment"); 375 return (TOK_ERR); 376 } 377 378 /* 379 * Single character tokens. 380 */ 381 if (strchr("():|", c) != NULL) 382 return (c); 383 384 if (c == '"' || c == '<') { 385 int32_t end = c; 386 size_t n = 0; 387 388 val = 1; 389 if (c == '<') { 390 val = 0; 391 end = '>'; 392 } 393 394 while ((c = tgetc()) != EOF) { 395 if (c == end) 396 break; 397 if (n == sizeof(nexttok) - 1) { 398 nexttok[n++] = '\0'; 399 warnx("filename too long '%s...'", nexttok); 400 return (TOK_ERR); 401 } 402 nexttok[n++] = c; 403 } 404 nexttok[n++] = '\0'; 405 return (TOK_FILENAME); 406 } 407 408 /* 409 * Sort out numbers. 410 */ 411 if (isdigit(c)) { 412 size_t n = 0; 413 nexttok[n++] = c; 414 while ((c = tgetc()) != EOF) { 415 if (!isdigit(c)) { 416 if (tungetc(c) < 0) 417 return (TOK_ERR); 418 break; 419 } 420 if (n == sizeof(nexttok) - 1) { 421 nexttok[n++] = '\0'; 422 warnx("number too long '%s...'", nexttok); 423 return (TOK_ERR); 424 } 425 nexttok[n++] = c; 426 } 427 nexttok[n++] = '\0'; 428 sscanf(nexttok, "%lu", &val); 429 return (TOK_NUM); 430 } 431 432 /* 433 * So that has to be a string. 434 */ 435 if (isalpha(c) || c == '_' || c == '-') { 436 size_t n = 0; 437 nexttok[n++] = c; 438 while ((c = tgetc()) != EOF) { 439 if (!isalnum(c) && c != '_' && c != '-') { 440 if (tungetc (c) < 0) 441 return (TOK_ERR); 442 break; 443 } 444 if (n == sizeof(nexttok) - 1) { 445 nexttok[n++] = '\0'; 446 warnx("string too long '%s...'", nexttok); 447 return (TOK_ERR); 448 } 449 nexttok[n++] = c; 450 } 451 nexttok[n++] = '\0'; 452 453 /* 454 * Keywords. 455 */ 456 for (c = 0; keywords[c].str != NULL; c++) 457 if (strcmp(keywords[c].str, nexttok) == 0) { 458 val = keywords[c].val; 459 return (keywords[c].tok); 460 } 461 462 if ((t = snmp_enumtc_lookup(snmptoolctx, nexttok)) != NULL) { 463 val = t->syntax; 464 return (TOK_DEFTYPE); 465 } 466 467 return (TOK_STR); 468 } 469 470 if (isprint(c)) 471 warnx("%u: unexpected character '%c'", input->lno, c); 472 else 473 warnx("%u: unexpected character 0x%02x", input->lno, (u_int) c); 474 475 return (TOK_ERR); 476 } 477 478 /* 479 * Update table information. 480 */ 481 static struct snmp_index_entry * 482 snmp_import_update_table(enum snmp_tbl_entry te, struct snmp_index_entry *tbl) 483 { 484 switch (te) { 485 case ENTRY_NONE: 486 if (table_data.tbl_type == ENTRY_NONE) 487 return (NULL); 488 if (table_data.tbl_type == ENTRY_INDEX) 489 table_data.table_idx = NULL; 490 table_data.tbl_type--; 491 return (NULL); 492 493 case ENTRY_INDEX: 494 if (tbl == NULL) 495 warnx("No table_index to add!!!"); 496 table_data.table_idx = tbl; 497 table_data.tbl_type = ENTRY_INDEX; 498 return (tbl); 499 500 case ENTRY_DATA: 501 if (table_data.tbl_type == ENTRY_INDEX) { 502 table_data.tbl_type = ENTRY_DATA; 503 return (table_data.table_idx); 504 } 505 return (NULL); 506 507 default: 508 /* NOTREACHED */ 509 warnx("Unknown table entry type!!!"); 510 break; 511 } 512 513 return (NULL); 514 } 515 516 static int32_t 517 parse_enum(struct snmp_toolinfo *snmptoolctx, int32_t *tok, 518 struct enum_pairs *enums) 519 { 520 while ((*tok = gettoken(snmptoolctx)) == TOK_STR) { 521 if (enum_pair_insert(enums, val, nexttok) < 0) 522 return (-1); 523 if ((*tok = gettoken(snmptoolctx)) != TOK_NUM) 524 break; 525 } 526 527 if (*tok != ')') { 528 warnx("')' at end of enums"); 529 return (-1); 530 } 531 532 return (1); 533 } 534 535 static int32_t 536 parse_subtype(struct snmp_toolinfo *snmptoolctx, int32_t *tok, 537 enum snmp_tc *tc) 538 { 539 if ((*tok = gettoken(snmptoolctx)) != TOK_STR) { 540 warnx("subtype expected after '|'"); 541 return (-1); 542 } 543 544 *tc = snmp_get_tc(nexttok); 545 *tok = gettoken(snmptoolctx); 546 547 return (1); 548 } 549 550 static int32_t 551 parse_type(struct snmp_toolinfo *snmptoolctx, int32_t *tok, 552 enum snmp_tc *tc, struct enum_pairs **snmp_enum) 553 { 554 int32_t syntax, mem; 555 556 syntax = val; 557 *tc = 0; 558 559 if (*tok == TOK_ENUM || *tok == TOK_BITS) { 560 if (*snmp_enum == NULL) { 561 if ((*snmp_enum = enum_pairs_init()) == NULL) 562 return (-1); 563 mem = 1; 564 *tc = SNMP_TC_OWN; 565 } else 566 mem = 0; 567 568 if (gettoken(snmptoolctx) != '(') { 569 warnx("'(' expected after ENUM/BITS"); 570 return (-1); 571 } 572 573 if ((*tok = gettoken(snmptoolctx)) != TOK_NUM) { 574 warnx("need value for ENUM//BITS"); 575 if (mem == 1) { 576 free(*snmp_enum); 577 *snmp_enum = NULL; 578 } 579 return (-1); 580 } 581 582 if (parse_enum(snmptoolctx, tok, *snmp_enum) < 0) { 583 enum_pairs_free(*snmp_enum); 584 *snmp_enum = NULL; 585 return (-1); 586 } 587 588 *tok = gettoken(snmptoolctx); 589 590 } else if (*tok == TOK_DEFTYPE) { 591 struct enum_type *t; 592 593 *tc = 0; 594 t = snmp_enumtc_lookup(snmptoolctx, nexttok); 595 if (t != NULL) 596 *snmp_enum = t->snmp_enum; 597 598 *tok = gettoken(snmptoolctx); 599 600 } else { 601 if ((*tok = gettoken(snmptoolctx)) == '|') { 602 if (parse_subtype(snmptoolctx, tok, tc) < 0) 603 return (-1); 604 } 605 } 606 607 return (syntax); 608 } 609 610 static int32_t 611 snmp_import_head(struct snmp_toolinfo *snmptoolctx) 612 { 613 enum tok tok; 614 615 if ((tok = gettoken(snmptoolctx)) == '(') 616 tok = gettoken(snmptoolctx); 617 618 if (tok != TOK_NUM || val > ASN_MAXID ) { 619 warnx("Suboid expected - line %d", input->lno); 620 return (-1); 621 } 622 623 if (gettoken(snmptoolctx) != TOK_STR) { 624 warnx("Node name expected at line %d", input->lno); 625 return (-1); 626 } 627 628 return (1); 629 } 630 631 static int32_t 632 snmp_import_table(struct snmp_toolinfo *snmptoolctx, struct snmp_oid2str *obj) 633 { 634 int32_t i, tok; 635 enum snmp_tc tc; 636 struct snmp_index_entry *entry; 637 638 if ((entry = calloc(1, sizeof(struct snmp_index_entry))) == NULL) { 639 syslog(LOG_ERR, "malloc() failed: %s", strerror(errno)); 640 return (-1); 641 } 642 643 STAILQ_INIT(&(entry->index_list)); 644 645 for (i = 0, tok = gettoken(snmptoolctx); i < SNMP_INDEXES_MAX; i++) { 646 int32_t syntax; 647 struct enum_pairs *enums = NULL; 648 649 if (tok != TOK_TYPE && tok != TOK_DEFTYPE && tok != TOK_ENUM && 650 tok != TOK_BITS) 651 break; 652 653 if ((syntax = parse_type(snmptoolctx, &tok, &tc, &enums)) < 0) { 654 enum_pairs_free(enums); 655 snmp_index_listfree(&(entry->index_list)); 656 free(entry); 657 return (-1); 658 } 659 660 if (snmp_syntax_insert(&(entry->index_list), enums, syntax, 661 tc) < 0) { 662 snmp_index_listfree(&(entry->index_list)); 663 enum_pairs_free(enums); 664 free(entry); 665 return (-1); 666 } 667 } 668 669 if (i == 0 || i > SNMP_INDEXES_MAX) { 670 warnx("Bad number of indexes at line %d", input->lno); 671 snmp_index_listfree(&(entry->index_list)); 672 free(entry); 673 return (-1); 674 } 675 676 if (tok != TOK_STR) { 677 warnx("String expected after indexes at line %d", input->lno); 678 snmp_index_listfree(&(entry->index_list)); 679 free(entry); 680 return (-1); 681 } 682 683 entry->string = obj->string; 684 entry->strlen = obj->strlen; 685 asn_append_oid(&(entry->var), &(obj->var)); 686 687 if ((i = snmp_table_insert(snmptoolctx, entry)) < 0) { 688 snmp_index_listfree(&(entry->index_list)); 689 free(entry); 690 return (-1); 691 } else if (i == 0) { 692 /* Same entry already present in lists. */ 693 free(entry->string); 694 free(entry); 695 return (0); 696 } 697 698 (void) snmp_import_update_table(ENTRY_INDEX, entry); 699 700 return (1); 701 } 702 703 /* 704 * Read everything after the syntax type that is certainly a leaf OID info. 705 */ 706 static int32_t 707 snmp_import_leaf(struct snmp_toolinfo *snmptoolctx, int32_t *tok, 708 struct snmp_oid2str *oid2str) 709 { 710 int32_t i, syntax; 711 712 if ((syntax = parse_type(snmptoolctx, tok, &(oid2str->tc), &(oid2str->snmp_enum))) 713 < 0) 714 return(-1); 715 716 oid2str->syntax = syntax; 717 /* 718 * That is the name of the function, corresponding to the entry. 719 * It is used by bsnmpd, but is not interesting for us. 720 */ 721 if (*tok == TOK_STR) 722 *tok = gettoken(snmptoolctx); 723 724 for (i = 0; i < SNMP_ACCESS_GETSET && *tok == TOK_ACCESS; i++) { 725 oid2str->access |= (uint32_t) val; 726 *tok = gettoken(snmptoolctx); 727 } 728 729 if (*tok != ')') { 730 warnx("')' expected at end of line %d", input->lno); 731 return (-1); 732 } 733 734 oid2str->table_idx = snmp_import_update_table(ENTRY_DATA, NULL); 735 736 if ((i = snmp_leaf_insert(snmptoolctx, oid2str)) < 0) { 737 warnx("Error adding leaf %s to list", oid2str->string); 738 return (-1); 739 } 740 741 /* 742 * Same entry is already present in the mapping lists and 743 * the new one was not inserted. 744 */ 745 if (i == 0) { 746 free(oid2str->string); 747 free(oid2str); 748 } 749 750 (void) snmp_import_update_table(ENTRY_NONE, NULL); 751 752 return (1); 753 } 754 755 static int32_t 756 snmp_import_object(struct snmp_toolinfo *snmptoolctx) 757 { 758 char *string; 759 int i; 760 int32_t tok; 761 struct snmp_oid2str *oid2str; 762 763 if (snmp_import_head(snmptoolctx) < 0) 764 return (-1); 765 766 if ((oid2str = calloc(1, sizeof(struct snmp_oid2str))) == NULL) { 767 syslog(LOG_ERR, "calloc() failed: %s", strerror(errno)); 768 return (-1); 769 } 770 771 if ((string = strdup(nexttok)) == NULL) { 772 syslog(LOG_ERR, "strdup() failed: %s", strerror(errno)); 773 free(oid2str); 774 return (-1); 775 } 776 777 oid2str->string = string; 778 oid2str->strlen = strlen(nexttok); 779 780 asn_append_oid(&(oid2str->var), &(current_oid)); 781 if (snmp_suboid_append(&(oid2str->var), (asn_subid_t) val) < 0) 782 goto error; 783 784 /* 785 * Prepared the entry - now figure out where to insert it. 786 * After the object we have following options: 787 * 1) new line, blank, ) - then it is an enum oid -> snmp_enumlist; 788 * 2) new line , ( - nonleaf oid -> snmp_nodelist; 789 * 2) ':' - table entry - a variable length SYNTAX_TYPE (one or more) 790 * may follow and second string must end line -> snmp_tablelist; 791 * 3) OID , string ) - this is a trap entry or a leaf -> snmp_oidlist; 792 * 4) SYNTAX_TYPE, string (not always), get/set modifier - always last 793 * and )- this is definitely a leaf. 794 */ 795 796 switch (tok = gettoken(snmptoolctx)) { 797 case ')': 798 if ((i = snmp_enum_insert(snmptoolctx, oid2str)) < 0) 799 goto error; 800 if (i == 0) { 801 free(oid2str->string); 802 free(oid2str); 803 } 804 return (1); 805 806 case '(': 807 if (snmp_suboid_append(¤t_oid, (asn_subid_t) val) < 0) 808 goto error; 809 810 /* 811 * Ignore the error for nodes since the .def files currently 812 * contain different strings for 1.3.6.1.2.1 - mibII. Only make 813 * sure the memory is freed and don't complain. 814 */ 815 if ((i = snmp_node_insert(snmptoolctx, oid2str)) <= 0) { 816 free(string); 817 free(oid2str); 818 } 819 return (snmp_import_object(snmptoolctx)); 820 821 case ':': 822 if (snmp_suboid_append(¤t_oid, (asn_subid_t) val) < 0) 823 goto error; 824 if (snmp_import_table(snmptoolctx, oid2str) < 0) 825 goto error; 826 /* 827 * A different table entry type was malloced and the data is 828 * contained there. 829 */ 830 free(oid2str); 831 return (1); 832 833 case TOK_TYPE: 834 /* FALLTHROUGH */ 835 case TOK_DEFTYPE: 836 /* FALLTHROUGH */ 837 case TOK_ENUM: 838 /* FALLTHROUGH */ 839 case TOK_BITS: 840 if (snmp_import_leaf(snmptoolctx, &tok, oid2str) < 0) 841 goto error; 842 return (1); 843 844 default: 845 warnx("Unexpected token at line %d - %s", input->lno, 846 input->fname); 847 break; 848 } 849 850 error: 851 snmp_mapping_entryfree(oid2str); 852 853 return (-1); 854 } 855 856 static int32_t 857 snmp_import_tree(struct snmp_toolinfo *snmptoolctx, int32_t *tok) 858 { 859 while (*tok != TOK_EOF) { 860 switch (*tok) { 861 case TOK_ERR: 862 return (-1); 863 case '(': 864 if (snmp_import_object(snmptoolctx) < 0) 865 return (-1); 866 break; 867 case ')': 868 if (snmp_suboid_pop(¤t_oid) < 0) 869 return (-1); 870 (void) snmp_import_update_table(ENTRY_NONE, NULL); 871 break; 872 default: 873 /* Anything else here would be illegal. */ 874 return (-1); 875 } 876 *tok = gettoken(snmptoolctx); 877 } 878 879 return (0); 880 } 881 882 static int32_t 883 snmp_import_top(struct snmp_toolinfo *snmptoolctx, int32_t *tok) 884 { 885 enum snmp_tc tc; 886 struct enum_type *t; 887 888 if (*tok == '(') 889 return (snmp_import_tree(snmptoolctx, tok)); 890 891 if (*tok == TOK_TYPEDEF) { 892 if ((*tok = gettoken(snmptoolctx)) != TOK_STR) { 893 warnx("type name expected after typedef - %s", 894 input->fname); 895 return (-1); 896 } 897 898 t = snmp_enumtc_init(nexttok); 899 900 *tok = gettoken(snmptoolctx); 901 t->is_enum = (*tok == TOK_ENUM); 902 t->is_bits = (*tok == TOK_BITS); 903 t->syntax = parse_type(snmptoolctx, tok, &tc, &(t->snmp_enum)); 904 snmp_enumtc_insert(snmptoolctx, t); 905 906 return (1); 907 } 908 909 if (*tok == TOK_INCLUDE) { 910 int i; 911 912 *tok = gettoken(snmptoolctx); 913 if (*tok != TOK_FILENAME) { 914 warnx("filename expected in include directive - %s", 915 nexttok); 916 return (-1); 917 } 918 919 if (( i = add_filename(snmptoolctx, nexttok, NULL, 1)) == 0) { 920 *tok = gettoken(snmptoolctx); 921 return (1); 922 } 923 924 if (i == -1) 925 return (-1); 926 927 input_fopen(nexttok); 928 *tok = gettoken(snmptoolctx); 929 return (1); 930 } 931 932 warnx("'(' or 'typedef' expected - %s", nexttok); 933 return (-1); 934 } 935 936 static int32_t 937 snmp_import(struct snmp_toolinfo *snmptoolctx) 938 { 939 int i; 940 int32_t tok; 941 942 tok = gettoken(snmptoolctx); 943 944 do 945 i = snmp_import_top(snmptoolctx, &tok); 946 while (i > 0); 947 948 return (i); 949 } 950 951 /* 952 * Read a .def file and import oid<->string mapping. 953 * Mappings are inserted into a global structure containing list for each OID 954 * syntax type. 955 */ 956 int32_t 957 snmp_import_file(struct snmp_toolinfo *snmptoolctx, struct fname *file) 958 { 959 int idx; 960 961 snmp_import_init(&(file->cut)); 962 input_fopen(file->name); 963 if ((idx = snmp_import(snmptoolctx)) < 0) 964 warnx("Failed to read mappings from file %s", file->name); 965 966 input_close(); 967 968 return (idx); 969 } 970