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