1216295Ssyrinx/*- 2216295Ssyrinx * Copyright (c) 2006 The FreeBSD Project 3216295Ssyrinx * All rights reserved. 4216295Ssyrinx * 5216295Ssyrinx * Author: Shteryana Shopova <syrinx@FreeBSD.org> 6216295Ssyrinx * 7216295Ssyrinx * Redistribution of this software and documentation and use in source and 8216295Ssyrinx * binary forms, with or without modification, are permitted provided that 9216295Ssyrinx * the following conditions are met: 10216295Ssyrinx * 11216295Ssyrinx * 1. Redistributions of source code or documentation must retain the above 12216295Ssyrinx * copyright notice, this list of conditions and the following disclaimer. 13216295Ssyrinx * 2. Redistributions in binary form must reproduce the above copyright 14216295Ssyrinx * notice, this list of conditions and the following disclaimer in the 15216295Ssyrinx * documentation and/or other materials provided with the distribution. 16216295Ssyrinx * 17216295Ssyrinx * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18216295Ssyrinx * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19216295Ssyrinx * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20216295Ssyrinx * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21216295Ssyrinx * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22216295Ssyrinx * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23216295Ssyrinx * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24216295Ssyrinx * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25216295Ssyrinx * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26216295Ssyrinx * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27216295Ssyrinx * SUCH DAMAGE. 28216295Ssyrinx * 29216295Ssyrinx * $FreeBSD$ 30216295Ssyrinx */ 31216295Ssyrinx 32216295Ssyrinx/* 33216295Ssyrinx * Read file containing table description - reuse magic from gensnmptree.c. 34216295Ssyrinx * Hopefully one day most of the code here will be part of libbsnmp and 35216295Ssyrinx * this duplication won't be necessary. 36216295Ssyrinx * 37216295Ssyrinx * Syntax is: 38216295Ssyrinx * --------- 39216295Ssyrinx * file := top | top file 40216295Ssyrinx * 41216295Ssyrinx * top := tree | typedef | include 42216295Ssyrinx * 43216295Ssyrinx * tree := head elements ')' 44216295Ssyrinx * 45216295Ssyrinx * entry := head ':' index STRING elements ')' 46216295Ssyrinx * 47216295Ssyrinx * leaf := head type STRING ACCESS ')' 48216295Ssyrinx * 49216295Ssyrinx * column := head type ACCESS ')' 50216295Ssyrinx * 51216295Ssyrinx * type := BASETYPE | BASETYPE '|' subtype | enum | bits 52216295Ssyrinx * 53216295Ssyrinx * subtype := STRING 54216295Ssyrinx * 55216295Ssyrinx * enum := ENUM '(' value ')' 56216295Ssyrinx * 57216295Ssyrinx * bits := BITS '(' value ')' 58216295Ssyrinx * 59216295Ssyrinx * value := INT STRING | INT STRING value 60216295Ssyrinx * 61216295Ssyrinx * head := '(' INT STRING 62216295Ssyrinx * 63216295Ssyrinx * elements := EMPTY | elements element 64216295Ssyrinx * 65216295Ssyrinx * element := tree | leaf | column 66216295Ssyrinx * 67216295Ssyrinx * index := type | index type 68216295Ssyrinx * 69216295Ssyrinx * typedef := 'typedef' STRING type 70216295Ssyrinx * 71216295Ssyrinx * include := 'include' filespec 72216295Ssyrinx * 73216295Ssyrinx * filespec := '"' STRING '"' | '<' STRING '>' 74216295Ssyrinx */ 75216295Ssyrinx 76216295Ssyrinx#include <sys/param.h> 77216295Ssyrinx#include <sys/queue.h> 78216295Ssyrinx#include <sys/uio.h> 79216295Ssyrinx 80216295Ssyrinx#include <ctype.h> 81216295Ssyrinx#include <err.h> 82216295Ssyrinx#include <errno.h> 83216295Ssyrinx#include <fcntl.h> 84216295Ssyrinx#include <stdio.h> 85216295Ssyrinx#include <stdlib.h> 86216295Ssyrinx#include <string.h> 87216295Ssyrinx#include <syslog.h> 88216295Ssyrinx#include <unistd.h> 89216295Ssyrinx 90216295Ssyrinx#include <bsnmp/asn1.h> 91216295Ssyrinx#include <bsnmp/snmp.h> 92216295Ssyrinx#include <bsnmp/snmpagent.h> /* SNMP_INDEXES_MAX */ 93216295Ssyrinx#include "bsnmptc.h" 94216295Ssyrinx#include "bsnmptools.h" 95216295Ssyrinx 96216295Ssyrinxenum snmp_tbl_entry { 97216295Ssyrinx ENTRY_NONE = 0, 98216295Ssyrinx ENTRY_INDEX, 99216295Ssyrinx ENTRY_DATA 100216295Ssyrinx}; 101216295Ssyrinx 102216295Ssyrinxenum { 103216295Ssyrinx FL_GET = 0x01, 104216295Ssyrinx FL_SET = 0x02, 105216295Ssyrinx}; 106216295Ssyrinx 107216295Ssyrinx/************************************************************ 108216295Ssyrinx * 109216295Ssyrinx * Allocate memory and panic just in the case... 110216295Ssyrinx */ 111216295Ssyrinxstatic void * 112216295Ssyrinxxalloc(size_t size) 113216295Ssyrinx{ 114216295Ssyrinx void *ptr; 115216295Ssyrinx 116216295Ssyrinx if ((ptr = malloc(size)) == NULL) 117216295Ssyrinx err(1, "allocing %zu bytes", size); 118216295Ssyrinx 119216295Ssyrinx return (ptr); 120216295Ssyrinx} 121216295Ssyrinx 122216295Ssyrinxstatic char * 123216295Ssyrinxsavestr(const char *s) 124216295Ssyrinx{ 125216295Ssyrinx if (s == NULL) 126216295Ssyrinx return (NULL); 127216295Ssyrinx 128216295Ssyrinx return (strcpy(xalloc(strlen(s) + 1), s)); 129216295Ssyrinx} 130216295Ssyrinx 131216295Ssyrinx/************************************************************ 132216295Ssyrinx * 133216295Ssyrinx * Input stack 134216295Ssyrinx */ 135216295Ssyrinxstruct input { 136216295Ssyrinx FILE *fp; 137216295Ssyrinx uint32_t lno; 138216295Ssyrinx char *fname; 139216295Ssyrinx char *path; 140216295Ssyrinx LIST_ENTRY(input) link; 141216295Ssyrinx}; 142216295Ssyrinx 143216295SsyrinxLIST_HEAD(, input) inputs = LIST_HEAD_INITIALIZER(inputs); 144216295Ssyrinxstruct input *input = NULL; 145216295Ssyrinxint32_t pbchar = -1; 146216295Ssyrinx 147216295Ssyrinx#define MAX_PATHS 100 148216295Ssyrinx 149216295Ssyrinxstatic const char *paths[MAX_PATHS + 1] = { 150216295Ssyrinx "/usr/share/snmp/defs", 151216295Ssyrinx "/usr/local/share/snmp/defs", 152216295Ssyrinx NULL 153216295Ssyrinx}; 154216295Ssyrinx 155216295Ssyrinxstatic void 156216295Ssyrinxinput_new(FILE *fp, const char *path, const char *fname) 157216295Ssyrinx{ 158216295Ssyrinx struct input *ip; 159216295Ssyrinx 160216295Ssyrinx ip = xalloc(sizeof(*ip)); 161216295Ssyrinx ip->fp = fp; 162216295Ssyrinx ip->lno = 1; 163216295Ssyrinx ip->fname = savestr(fname); 164216295Ssyrinx ip->path = savestr(path); 165216295Ssyrinx LIST_INSERT_HEAD(&inputs, ip, link); 166216295Ssyrinx 167216295Ssyrinx input = ip; 168216295Ssyrinx} 169216295Ssyrinx 170216295Ssyrinxstatic void 171216295Ssyrinxinput_close(void) 172216295Ssyrinx{ 173216295Ssyrinx if (input == NULL) 174216295Ssyrinx return; 175216295Ssyrinx 176216295Ssyrinx fclose(input->fp); 177216295Ssyrinx free(input->fname); 178216295Ssyrinx free(input->path); 179216295Ssyrinx LIST_REMOVE(input, link); 180216295Ssyrinx free(input); 181216295Ssyrinx 182216295Ssyrinx input = LIST_FIRST(&inputs); 183216295Ssyrinx} 184216295Ssyrinx 185216295Ssyrinxstatic FILE * 186216295Ssyrinxtryopen(const char *path, const char *fname) 187216295Ssyrinx{ 188216295Ssyrinx char *fn; 189216295Ssyrinx FILE *fp; 190216295Ssyrinx 191216295Ssyrinx if (path == NULL) 192216295Ssyrinx fn = savestr(fname); 193216295Ssyrinx else { 194216295Ssyrinx fn = xalloc(strlen(path) + strlen(fname) + 2); 195216295Ssyrinx sprintf(fn, "%s/%s", path, fname); 196216295Ssyrinx } 197216295Ssyrinx fp = fopen(fn, "r"); 198216295Ssyrinx free(fn); 199216295Ssyrinx return (fp); 200216295Ssyrinx} 201216295Ssyrinx 202216295Ssyrinxstatic int32_t 203216295Ssyrinxinput_fopen(const char *fname) 204216295Ssyrinx{ 205216295Ssyrinx FILE *fp; 206216295Ssyrinx u_int p; 207216295Ssyrinx 208216295Ssyrinx if (fname[0] == '/' || fname[0] == '.' || fname[0] == '~') { 209216295Ssyrinx if ((fp = tryopen(NULL, fname)) != NULL) { 210216295Ssyrinx input_new(fp, NULL, fname); 211216295Ssyrinx return (0); 212216295Ssyrinx } 213216295Ssyrinx 214216295Ssyrinx } else { 215216295Ssyrinx 216216295Ssyrinx for (p = 0; paths[p] != NULL; p++) 217216295Ssyrinx if ((fp = tryopen(paths[p], fname)) != NULL) { 218216295Ssyrinx input_new(fp, paths[p], fname); 219216295Ssyrinx return (0); 220216295Ssyrinx } 221216295Ssyrinx } 222216295Ssyrinx 223216295Ssyrinx warnx("cannot open '%s'", fname); 224216295Ssyrinx return (-1); 225216295Ssyrinx} 226216295Ssyrinx 227216295Ssyrinxstatic int32_t 228216295Ssyrinxtgetc(void) 229216295Ssyrinx{ 230216295Ssyrinx int c; 231216295Ssyrinx 232216295Ssyrinx if (pbchar != -1) { 233216295Ssyrinx c = pbchar; 234216295Ssyrinx pbchar = -1; 235216295Ssyrinx return (c); 236216295Ssyrinx } 237216295Ssyrinx 238216295Ssyrinx for (;;) { 239216295Ssyrinx if (input == NULL) 240216295Ssyrinx return (EOF); 241216295Ssyrinx 242216295Ssyrinx if ((c = getc(input->fp)) != EOF) 243216295Ssyrinx return (c); 244216295Ssyrinx 245216295Ssyrinx input_close(); 246216295Ssyrinx } 247216295Ssyrinx} 248216295Ssyrinx 249216295Ssyrinxstatic int32_t 250216295Ssyrinxtungetc(int c) 251216295Ssyrinx{ 252216295Ssyrinx 253216295Ssyrinx if (pbchar != -1) 254216295Ssyrinx return (-1); 255216295Ssyrinx 256216295Ssyrinx pbchar = c; 257216295Ssyrinx return (1); 258216295Ssyrinx} 259216295Ssyrinx 260216295Ssyrinx/************************************************************ 261216295Ssyrinx * 262216295Ssyrinx * Parsing input 263216295Ssyrinx */ 264216295Ssyrinxenum tok { 265216295Ssyrinx TOK_EOF = 0200, /* end-of-file seen */ 266216295Ssyrinx TOK_NUM, /* number */ 267216295Ssyrinx TOK_STR, /* string */ 268216295Ssyrinx TOK_ACCESS, /* access operator */ 269216295Ssyrinx TOK_TYPE, /* type operator */ 270216295Ssyrinx TOK_ENUM, /* enum token (kind of a type) */ 271216295Ssyrinx TOK_TYPEDEF, /* typedef directive */ 272216295Ssyrinx TOK_DEFTYPE, /* defined type */ 273216295Ssyrinx TOK_INCLUDE, /* include directive */ 274216295Ssyrinx TOK_FILENAME, /* filename ("foo.bar" or <foo.bar>) */ 275216295Ssyrinx TOK_BITS, /* bits token (kind of a type) */ 276216295Ssyrinx TOK_ERR /* unexpected char - exit */ 277216295Ssyrinx}; 278216295Ssyrinx 279216295Ssyrinxstatic const struct { 280216295Ssyrinx const char *str; 281216295Ssyrinx enum tok tok; 282216295Ssyrinx uint32_t val; 283216295Ssyrinx} keywords[] = { 284216295Ssyrinx { "GET", TOK_ACCESS, FL_GET }, 285216295Ssyrinx { "SET", TOK_ACCESS, FL_SET }, 286216295Ssyrinx { "NULL", TOK_TYPE, SNMP_SYNTAX_NULL }, 287216295Ssyrinx { "INTEGER", TOK_TYPE, SNMP_SYNTAX_INTEGER }, 288216295Ssyrinx { "INTEGER32", TOK_TYPE, SNMP_SYNTAX_INTEGER }, 289216295Ssyrinx { "UNSIGNED32", TOK_TYPE, SNMP_SYNTAX_GAUGE }, 290216295Ssyrinx { "OCTETSTRING", TOK_TYPE, SNMP_SYNTAX_OCTETSTRING }, 291216295Ssyrinx { "IPADDRESS", TOK_TYPE, SNMP_SYNTAX_IPADDRESS }, 292216295Ssyrinx { "OID", TOK_TYPE, SNMP_SYNTAX_OID }, 293216295Ssyrinx { "TIMETICKS", TOK_TYPE, SNMP_SYNTAX_TIMETICKS }, 294216295Ssyrinx { "COUNTER", TOK_TYPE, SNMP_SYNTAX_COUNTER }, 295216295Ssyrinx { "GAUGE", TOK_TYPE, SNMP_SYNTAX_GAUGE }, 296216295Ssyrinx { "COUNTER64", TOK_TYPE, SNMP_SYNTAX_COUNTER64 }, 297216295Ssyrinx { "ENUM", TOK_ENUM, SNMP_SYNTAX_INTEGER }, 298216295Ssyrinx { "BITS", TOK_BITS, SNMP_SYNTAX_OCTETSTRING }, 299216295Ssyrinx { "typedef", TOK_TYPEDEF, 0 }, 300216295Ssyrinx { "include", TOK_INCLUDE, 0 }, 301216295Ssyrinx { NULL, 0, 0 } 302216295Ssyrinx}; 303216295Ssyrinx 304216295Ssyrinxstruct { 305216295Ssyrinx /* Current OID type, regarding table membership. */ 306216295Ssyrinx enum snmp_tbl_entry tbl_type; 307216295Ssyrinx /* A pointer to a structure in table list to add to its members. */ 308216295Ssyrinx struct snmp_index_entry *table_idx; 309216295Ssyrinx} table_data; 310216295Ssyrinx 311216295Ssyrinxstruct asn_oid current_oid; 312216295Ssyrinxchar nexttok[MAXSTR]; 313216295Ssyrinxu_long val; /* integer values */ 314216295Ssyrinxint32_t all_cond; /* all conditions are true */ 315216295Ssyrinxint32_t saved_token = -1; 316216295Ssyrinx 317216295Ssyrinx/* Prepare the global data before parsing a new file. */ 318216295Ssyrinxstatic void 319216295Ssyrinxsnmp_import_init(struct asn_oid *append) 320216295Ssyrinx{ 321216295Ssyrinx memset(&table_data, 0, sizeof(table_data)); 322216295Ssyrinx memset(¤t_oid, 0, sizeof(struct asn_oid)); 323216295Ssyrinx memset(nexttok, 0, MAXSTR); 324216295Ssyrinx 325216295Ssyrinx if (append != NULL) 326216295Ssyrinx asn_append_oid(¤t_oid, append); 327216295Ssyrinx 328216295Ssyrinx all_cond = 0; 329216295Ssyrinx val = 0; 330216295Ssyrinx saved_token = -1; 331216295Ssyrinx} 332216295Ssyrinx 333216295Ssyrinxstatic int32_t 334216295Ssyrinxgettoken(struct snmp_toolinfo *snmptoolctx) 335216295Ssyrinx{ 336216295Ssyrinx int c; 337216295Ssyrinx struct enum_type *t; 338216295Ssyrinx 339216295Ssyrinx if (saved_token != -1) { 340216295Ssyrinx c = saved_token; 341216295Ssyrinx saved_token = -1; 342216295Ssyrinx return (c); 343216295Ssyrinx } 344216295Ssyrinx 345216295Ssyrinx again: 346216295Ssyrinx /* 347216295Ssyrinx * Skip any whitespace before the next token. 348216295Ssyrinx */ 349216295Ssyrinx while ((c = tgetc()) != EOF) { 350216295Ssyrinx if (c == '\n') 351216295Ssyrinx input->lno++; 352216295Ssyrinx if (!isspace(c)) 353216295Ssyrinx break; 354216295Ssyrinx } 355216295Ssyrinx if (c == EOF) 356216295Ssyrinx return (TOK_EOF); 357216295Ssyrinx 358216295Ssyrinx if (!isascii(c)) { 359216295Ssyrinx warnx("unexpected character %#2x", (u_int) c); 360216295Ssyrinx return (TOK_ERR); 361216295Ssyrinx } 362216295Ssyrinx 363216295Ssyrinx /* 364216295Ssyrinx * Skip comments. 365216295Ssyrinx */ 366216295Ssyrinx if (c == '#') { 367216295Ssyrinx while ((c = tgetc()) != EOF) { 368216295Ssyrinx if (c == '\n') { 369216295Ssyrinx input->lno++; 370216295Ssyrinx goto again; 371216295Ssyrinx } 372216295Ssyrinx } 373216295Ssyrinx warnx("unexpected EOF in comment"); 374216295Ssyrinx return (TOK_ERR); 375216295Ssyrinx } 376216295Ssyrinx 377216295Ssyrinx /* 378216295Ssyrinx * Single character tokens. 379216295Ssyrinx */ 380216295Ssyrinx if (strchr("():|", c) != NULL) 381216295Ssyrinx return (c); 382216295Ssyrinx 383216295Ssyrinx if (c == '"' || c == '<') { 384216295Ssyrinx int32_t end = c; 385216295Ssyrinx size_t n = 0; 386216295Ssyrinx 387216295Ssyrinx val = 1; 388216295Ssyrinx if (c == '<') { 389216295Ssyrinx val = 0; 390216295Ssyrinx end = '>'; 391216295Ssyrinx } 392216295Ssyrinx 393216295Ssyrinx while ((c = tgetc()) != EOF) { 394216295Ssyrinx if (c == end) 395216295Ssyrinx break; 396216295Ssyrinx if (n == sizeof(nexttok) - 1) { 397216295Ssyrinx nexttok[n++] = '\0'; 398216295Ssyrinx warnx("filename too long '%s...'", nexttok); 399216295Ssyrinx return (TOK_ERR); 400216295Ssyrinx } 401216295Ssyrinx nexttok[n++] = c; 402216295Ssyrinx } 403216295Ssyrinx nexttok[n++] = '\0'; 404216295Ssyrinx return (TOK_FILENAME); 405216295Ssyrinx } 406216295Ssyrinx 407216295Ssyrinx /* 408216295Ssyrinx * Sort out numbers. 409216295Ssyrinx */ 410216295Ssyrinx if (isdigit(c)) { 411216295Ssyrinx size_t n = 0; 412216295Ssyrinx nexttok[n++] = c; 413216295Ssyrinx while ((c = tgetc()) != EOF) { 414216295Ssyrinx if (!isdigit(c)) { 415216295Ssyrinx if (tungetc(c) < 0) 416216295Ssyrinx return (TOK_ERR); 417216295Ssyrinx break; 418216295Ssyrinx } 419216295Ssyrinx if (n == sizeof(nexttok) - 1) { 420216295Ssyrinx nexttok[n++] = '\0'; 421216295Ssyrinx warnx("number too long '%s...'", nexttok); 422216295Ssyrinx return (TOK_ERR); 423216295Ssyrinx } 424216295Ssyrinx nexttok[n++] = c; 425216295Ssyrinx } 426216295Ssyrinx nexttok[n++] = '\0'; 427216295Ssyrinx sscanf(nexttok, "%lu", &val); 428216295Ssyrinx return (TOK_NUM); 429216295Ssyrinx } 430216295Ssyrinx 431216295Ssyrinx /* 432216295Ssyrinx * So that has to be a string. 433216295Ssyrinx */ 434216295Ssyrinx if (isalpha(c) || c == '_' || c == '-') { 435216295Ssyrinx size_t n = 0; 436216295Ssyrinx nexttok[n++] = c; 437216295Ssyrinx while ((c = tgetc()) != EOF) { 438216295Ssyrinx if (!isalnum(c) && c != '_' && c != '-') { 439216295Ssyrinx if (tungetc (c) < 0) 440216295Ssyrinx return (TOK_ERR); 441216295Ssyrinx break; 442216295Ssyrinx } 443216295Ssyrinx if (n == sizeof(nexttok) - 1) { 444216295Ssyrinx nexttok[n++] = '\0'; 445216295Ssyrinx warnx("string too long '%s...'", nexttok); 446216295Ssyrinx return (TOK_ERR); 447216295Ssyrinx } 448216295Ssyrinx nexttok[n++] = c; 449216295Ssyrinx } 450216295Ssyrinx nexttok[n++] = '\0'; 451216295Ssyrinx 452216295Ssyrinx /* 453216295Ssyrinx * Keywords. 454216295Ssyrinx */ 455216295Ssyrinx for (c = 0; keywords[c].str != NULL; c++) 456216295Ssyrinx if (strcmp(keywords[c].str, nexttok) == 0) { 457216295Ssyrinx val = keywords[c].val; 458216295Ssyrinx return (keywords[c].tok); 459216295Ssyrinx } 460216295Ssyrinx 461216295Ssyrinx if ((t = snmp_enumtc_lookup(snmptoolctx, nexttok)) != NULL) { 462216295Ssyrinx val = t->syntax; 463216295Ssyrinx return (TOK_DEFTYPE); 464216295Ssyrinx } 465216295Ssyrinx 466216295Ssyrinx return (TOK_STR); 467216295Ssyrinx } 468216295Ssyrinx 469216295Ssyrinx if (isprint(c)) 470216295Ssyrinx warnx("%u: unexpected character '%c'", input->lno, c); 471216295Ssyrinx else 472216295Ssyrinx warnx("%u: unexpected character 0x%02x", input->lno, (u_int) c); 473216295Ssyrinx 474216295Ssyrinx return (TOK_ERR); 475216295Ssyrinx} 476216295Ssyrinx 477216295Ssyrinx/* 478216295Ssyrinx * Update table information. 479216295Ssyrinx */ 480216295Ssyrinxstatic struct snmp_index_entry * 481216295Ssyrinxsnmp_import_update_table(enum snmp_tbl_entry te, struct snmp_index_entry *tbl) 482216295Ssyrinx{ 483216295Ssyrinx switch (te) { 484216295Ssyrinx case ENTRY_NONE: 485216295Ssyrinx if (table_data.tbl_type == ENTRY_NONE) 486216295Ssyrinx return (NULL); 487216295Ssyrinx if (table_data.tbl_type == ENTRY_INDEX) 488216295Ssyrinx table_data.table_idx = NULL; 489216295Ssyrinx table_data.tbl_type--; 490216295Ssyrinx return (NULL); 491216295Ssyrinx 492216295Ssyrinx case ENTRY_INDEX: 493216295Ssyrinx if (tbl == NULL) 494216295Ssyrinx warnx("No table_index to add!!!"); 495216295Ssyrinx table_data.table_idx = tbl; 496216295Ssyrinx table_data.tbl_type = ENTRY_INDEX; 497216295Ssyrinx return (tbl); 498216295Ssyrinx 499216295Ssyrinx case ENTRY_DATA: 500216295Ssyrinx if (table_data.tbl_type == ENTRY_INDEX) { 501216295Ssyrinx table_data.tbl_type = ENTRY_DATA; 502216295Ssyrinx return (table_data.table_idx); 503216295Ssyrinx } 504216295Ssyrinx return (NULL); 505216295Ssyrinx 506216295Ssyrinx default: 507216295Ssyrinx /* NOTREACHED */ 508216295Ssyrinx warnx("Unknown table entry type!!!"); 509216295Ssyrinx break; 510216295Ssyrinx } 511216295Ssyrinx 512216295Ssyrinx return (NULL); 513216295Ssyrinx} 514216295Ssyrinx 515216295Ssyrinxstatic int32_t 516216295Ssyrinxparse_enum(struct snmp_toolinfo *snmptoolctx, enum tok *tok, 517216295Ssyrinx struct enum_pairs *enums) 518216295Ssyrinx{ 519216295Ssyrinx while ((*tok = gettoken(snmptoolctx)) == TOK_STR) { 520216295Ssyrinx if (enum_pair_insert(enums, val, nexttok) < 0) 521216295Ssyrinx return (-1); 522216295Ssyrinx if ((*tok = gettoken(snmptoolctx)) != TOK_NUM) 523216295Ssyrinx break; 524216295Ssyrinx } 525216295Ssyrinx 526216295Ssyrinx if (*tok != ')') { 527216295Ssyrinx warnx("')' at end of enums"); 528216295Ssyrinx return (-1); 529216295Ssyrinx } 530216295Ssyrinx 531216295Ssyrinx return (1); 532216295Ssyrinx} 533216295Ssyrinx 534216295Ssyrinxstatic int32_t 535216295Ssyrinxparse_subtype(struct snmp_toolinfo *snmptoolctx, enum tok *tok, 536216295Ssyrinx enum snmp_tc *tc) 537216295Ssyrinx{ 538216295Ssyrinx if ((*tok = gettoken(snmptoolctx)) != TOK_STR) { 539216295Ssyrinx warnx("subtype expected after '|'"); 540216295Ssyrinx return (-1); 541216295Ssyrinx } 542216295Ssyrinx 543216295Ssyrinx *tc = snmp_get_tc(nexttok); 544216295Ssyrinx *tok = gettoken(snmptoolctx); 545216295Ssyrinx 546216295Ssyrinx return (1); 547216295Ssyrinx} 548216295Ssyrinx 549216295Ssyrinxstatic int32_t 550216295Ssyrinxparse_type(struct snmp_toolinfo *snmptoolctx, enum tok *tok, 551216295Ssyrinx enum snmp_tc *tc, struct enum_pairs **snmp_enum) 552216295Ssyrinx{ 553216295Ssyrinx int32_t syntax, mem; 554216295Ssyrinx 555216295Ssyrinx syntax = val; 556216295Ssyrinx *tc = 0; 557216295Ssyrinx 558216295Ssyrinx if (*tok == TOK_ENUM || *tok == TOK_BITS) { 559216295Ssyrinx if (*snmp_enum == NULL) { 560216295Ssyrinx if ((*snmp_enum = enum_pairs_init()) == NULL) 561216295Ssyrinx return (-1); 562216295Ssyrinx mem = 1; 563216295Ssyrinx *tc = SNMP_TC_OWN; 564216295Ssyrinx } else 565216295Ssyrinx mem = 0; 566216295Ssyrinx 567216295Ssyrinx if (gettoken(snmptoolctx) != '(') { 568216295Ssyrinx warnx("'(' expected after ENUM/BITS"); 569216295Ssyrinx return (-1); 570216295Ssyrinx } 571216295Ssyrinx 572216295Ssyrinx if ((*tok = gettoken(snmptoolctx)) != TOK_NUM) { 573216295Ssyrinx warnx("need value for ENUM//BITS"); 574216295Ssyrinx if (mem == 1) { 575216295Ssyrinx free(*snmp_enum); 576216295Ssyrinx *snmp_enum = NULL; 577216295Ssyrinx } 578216295Ssyrinx return (-1); 579216295Ssyrinx } 580216295Ssyrinx 581216295Ssyrinx if (parse_enum(snmptoolctx, tok, *snmp_enum) < 0) { 582216295Ssyrinx enum_pairs_free(*snmp_enum); 583216295Ssyrinx *snmp_enum = NULL; 584216295Ssyrinx return (-1); 585216295Ssyrinx } 586216295Ssyrinx 587216295Ssyrinx *tok = gettoken(snmptoolctx); 588216295Ssyrinx 589216295Ssyrinx } else if (*tok == TOK_DEFTYPE) { 590216295Ssyrinx struct enum_type *t; 591216295Ssyrinx 592216295Ssyrinx *tc = 0; 593216295Ssyrinx t = snmp_enumtc_lookup(snmptoolctx, nexttok); 594216295Ssyrinx if (t != NULL) 595216295Ssyrinx *snmp_enum = t->snmp_enum; 596216295Ssyrinx 597216295Ssyrinx *tok = gettoken(snmptoolctx); 598216295Ssyrinx 599216295Ssyrinx } else { 600216295Ssyrinx if ((*tok = gettoken(snmptoolctx)) == '|') { 601216295Ssyrinx if (parse_subtype(snmptoolctx, tok, tc) < 0) 602216295Ssyrinx return (-1); 603216295Ssyrinx } 604216295Ssyrinx } 605216295Ssyrinx 606216295Ssyrinx return (syntax); 607216295Ssyrinx} 608216295Ssyrinx 609216295Ssyrinxstatic int32_t 610216295Ssyrinxsnmp_import_head(struct snmp_toolinfo *snmptoolctx) 611216295Ssyrinx{ 612216295Ssyrinx enum tok tok; 613216295Ssyrinx 614216295Ssyrinx if ((tok = gettoken(snmptoolctx)) == '(') 615216295Ssyrinx tok = gettoken(snmptoolctx); 616216295Ssyrinx 617216295Ssyrinx if (tok != TOK_NUM || val > ASN_MAXID ) { 618216295Ssyrinx warnx("Suboid expected - line %d", input->lno); 619216295Ssyrinx return (-1); 620216295Ssyrinx } 621216295Ssyrinx 622216295Ssyrinx if (gettoken(snmptoolctx) != TOK_STR) { 623216295Ssyrinx warnx("Node name expected at line %d", input->lno); 624216295Ssyrinx return (-1); 625216295Ssyrinx } 626216295Ssyrinx 627216295Ssyrinx return (1); 628216295Ssyrinx} 629216295Ssyrinx 630216295Ssyrinxstatic int32_t 631216295Ssyrinxsnmp_import_table(struct snmp_toolinfo *snmptoolctx, struct snmp_oid2str *obj) 632216295Ssyrinx{ 633216295Ssyrinx int32_t i; 634216295Ssyrinx enum snmp_tc tc; 635216295Ssyrinx enum tok tok; 636216295Ssyrinx struct snmp_index_entry *entry; 637216295Ssyrinx 638216295Ssyrinx if ((entry = malloc(sizeof(struct snmp_index_entry))) == NULL) { 639216295Ssyrinx syslog(LOG_ERR, "malloc() failed: %s", strerror(errno)); 640216295Ssyrinx return (-1); 641216295Ssyrinx } 642216295Ssyrinx 643216295Ssyrinx memset(entry, 0, sizeof(struct snmp_index_entry)); 644216295Ssyrinx STAILQ_INIT(&(entry->index_list)); 645216295Ssyrinx 646216295Ssyrinx for (i = 0, tok = gettoken(snmptoolctx); i < SNMP_INDEXES_MAX; i++) { 647216295Ssyrinx int32_t syntax; 648216295Ssyrinx struct enum_pairs *enums = NULL; 649216295Ssyrinx 650216295Ssyrinx if (tok != TOK_TYPE && tok != TOK_DEFTYPE && tok != TOK_ENUM && 651216295Ssyrinx tok != TOK_BITS) 652216295Ssyrinx break; 653216295Ssyrinx 654216295Ssyrinx if ((syntax = parse_type(snmptoolctx, &tok, &tc, &enums)) < 0) { 655216295Ssyrinx enum_pairs_free(enums); 656216295Ssyrinx snmp_index_listfree(&(entry->index_list)); 657216295Ssyrinx free(entry); 658216295Ssyrinx return (-1); 659216295Ssyrinx } 660216295Ssyrinx 661216295Ssyrinx if (snmp_syntax_insert(&(entry->index_list), enums, syntax, 662216295Ssyrinx tc) < 0) { 663216295Ssyrinx snmp_index_listfree(&(entry->index_list)); 664216295Ssyrinx enum_pairs_free(enums); 665216295Ssyrinx free(entry); 666216295Ssyrinx return (-1); 667216295Ssyrinx } 668216295Ssyrinx } 669216295Ssyrinx 670216295Ssyrinx if (i == 0 || i > SNMP_INDEXES_MAX) { 671216295Ssyrinx warnx("Bad number of indexes at line %d", input->lno); 672216295Ssyrinx snmp_index_listfree(&(entry->index_list)); 673216295Ssyrinx free(entry); 674216295Ssyrinx return (-1); 675216295Ssyrinx } 676216295Ssyrinx 677216295Ssyrinx if (tok != TOK_STR) { 678216295Ssyrinx warnx("String expected after indexes at line %d", input->lno); 679216295Ssyrinx snmp_index_listfree(&(entry->index_list)); 680216295Ssyrinx free(entry); 681216295Ssyrinx return (-1); 682216295Ssyrinx } 683216295Ssyrinx 684216295Ssyrinx entry->string = obj->string; 685216295Ssyrinx entry->strlen = obj->strlen; 686216295Ssyrinx asn_append_oid(&(entry->var), &(obj->var)); 687216295Ssyrinx 688216295Ssyrinx if ((i = snmp_table_insert(snmptoolctx, entry)) < 0) { 689216295Ssyrinx snmp_index_listfree(&(entry->index_list)); 690216295Ssyrinx free(entry); 691216295Ssyrinx return (-1); 692216295Ssyrinx } else if (i == 0) { 693216295Ssyrinx /* Same entry already present in lists. */ 694216295Ssyrinx free(entry->string); 695216295Ssyrinx free(entry); 696216295Ssyrinx } 697216295Ssyrinx 698216295Ssyrinx (void) snmp_import_update_table(ENTRY_INDEX, entry); 699216295Ssyrinx 700216295Ssyrinx return (1); 701216295Ssyrinx} 702216295Ssyrinx 703216295Ssyrinx/* 704216295Ssyrinx * Read everything after the syntax type that is certainly a leaf OID info. 705216295Ssyrinx */ 706216295Ssyrinxstatic int32_t 707216295Ssyrinxsnmp_import_leaf(struct snmp_toolinfo *snmptoolctx, enum tok *tok, 708216295Ssyrinx struct snmp_oid2str *oid2str) 709216295Ssyrinx{ 710216295Ssyrinx int32_t i, syntax; 711216295Ssyrinx 712216295Ssyrinx if ((syntax = parse_type(snmptoolctx, tok, &(oid2str->tc), &(oid2str->snmp_enum))) 713216295Ssyrinx < 0) 714216295Ssyrinx return(-1); 715216295Ssyrinx 716216295Ssyrinx oid2str->syntax = syntax; 717216295Ssyrinx /* 718216295Ssyrinx * That is the name of the function, corresponding to the entry. 719216295Ssyrinx * It is used by bsnmpd, but is not interesting for us. 720216295Ssyrinx */ 721216295Ssyrinx if (*tok == TOK_STR) 722216295Ssyrinx *tok = gettoken(snmptoolctx); 723216295Ssyrinx 724216295Ssyrinx for (i = 0; i < SNMP_ACCESS_GETSET && *tok == TOK_ACCESS; i++) { 725216295Ssyrinx oid2str->access |= (uint32_t) val; 726216295Ssyrinx *tok = gettoken(snmptoolctx); 727216295Ssyrinx } 728216295Ssyrinx 729216295Ssyrinx if (*tok != ')') { 730216295Ssyrinx warnx("')' expected at end of line %d", input->lno); 731216295Ssyrinx return (-1); 732216295Ssyrinx } 733216295Ssyrinx 734216295Ssyrinx oid2str->table_idx = snmp_import_update_table(ENTRY_DATA, NULL); 735216295Ssyrinx 736216295Ssyrinx if ((i = snmp_leaf_insert(snmptoolctx, oid2str)) < 0) { 737216295Ssyrinx warnx("Error adding leaf %s to list", oid2str->string); 738216295Ssyrinx return (-1); 739216295Ssyrinx } 740216295Ssyrinx 741216295Ssyrinx /* 742216295Ssyrinx * Same entry is already present in the mapping lists and 743216295Ssyrinx * the new one was not inserted. 744216295Ssyrinx */ 745216295Ssyrinx if (i == 0) { 746216295Ssyrinx free(oid2str->string); 747216295Ssyrinx free(oid2str); 748216295Ssyrinx } 749216295Ssyrinx 750216295Ssyrinx (void) snmp_import_update_table(ENTRY_NONE, NULL); 751216295Ssyrinx 752216295Ssyrinx return (1); 753216295Ssyrinx} 754216295Ssyrinx 755216295Ssyrinxstatic int32_t 756216295Ssyrinxsnmp_import_object(struct snmp_toolinfo *snmptoolctx) 757216295Ssyrinx{ 758216295Ssyrinx char *string; 759216295Ssyrinx int i; 760216295Ssyrinx enum tok tok; 761216295Ssyrinx struct snmp_oid2str *oid2str; 762216295Ssyrinx 763216295Ssyrinx if (snmp_import_head(snmptoolctx) < 0) 764216295Ssyrinx return (-1); 765216295Ssyrinx 766216295Ssyrinx if ((oid2str = malloc(sizeof(struct snmp_oid2str))) == NULL) { 767216295Ssyrinx syslog(LOG_ERR, "malloc() failed: %s", strerror(errno)); 768216295Ssyrinx return (-1); 769216295Ssyrinx } 770216295Ssyrinx 771216295Ssyrinx if ((string = malloc(strlen(nexttok) + 1)) == NULL) { 772216295Ssyrinx syslog(LOG_ERR, "malloc() failed: %s", strerror(errno)); 773216295Ssyrinx free(oid2str); 774216295Ssyrinx return (-1); 775216295Ssyrinx } 776216295Ssyrinx 777216295Ssyrinx memset(oid2str, 0, sizeof(struct snmp_oid2str)); 778216295Ssyrinx strlcpy(string, nexttok, strlen(nexttok) + 1); 779216295Ssyrinx oid2str->string = string; 780216295Ssyrinx oid2str->strlen = strlen(nexttok); 781216295Ssyrinx 782216295Ssyrinx asn_append_oid(&(oid2str->var), &(current_oid)); 783216295Ssyrinx if (snmp_suboid_append(&(oid2str->var), (asn_subid_t) val) < 0) 784216295Ssyrinx goto error; 785216295Ssyrinx 786216295Ssyrinx /* 787216295Ssyrinx * Prepared the entry - now figure out where to insert it. 788216295Ssyrinx * After the object we have following options: 789216295Ssyrinx * 1) new line, blank, ) - then it is an enum oid -> snmp_enumlist; 790216295Ssyrinx * 2) new line , ( - nonleaf oid -> snmp_nodelist; 791216295Ssyrinx * 2) ':' - table entry - a variable length SYNTAX_TYPE (one or more) 792216295Ssyrinx * may follow and second string must end line -> snmp_tablelist; 793216295Ssyrinx * 3) OID , string ) - this is a trap entry or a leaf -> snmp_oidlist; 794216295Ssyrinx * 4) SYNTAX_TYPE, string (not always), get/set modifier - always last 795216295Ssyrinx * and )- this is definitely a leaf. 796216295Ssyrinx */ 797216295Ssyrinx 798216295Ssyrinx switch (tok = gettoken(snmptoolctx)) { 799216295Ssyrinx case ')': 800216295Ssyrinx if ((i = snmp_enum_insert(snmptoolctx, oid2str)) < 0) 801216295Ssyrinx goto error; 802216295Ssyrinx if (i == 0) { 803216295Ssyrinx free(oid2str->string); 804216295Ssyrinx free(oid2str); 805216295Ssyrinx } 806216295Ssyrinx return (1); 807216295Ssyrinx 808216295Ssyrinx case '(': 809216295Ssyrinx if (snmp_suboid_append(¤t_oid, (asn_subid_t) val) < 0) 810216295Ssyrinx goto error; 811216295Ssyrinx 812216295Ssyrinx /* 813216295Ssyrinx * Ignore the error for nodes since the .def files currently 814216295Ssyrinx * contain different strings for 1.3.6.1.2.1 - mibII. Only make 815216295Ssyrinx * sure the memory is freed and don't complain. 816216295Ssyrinx */ 817216295Ssyrinx if ((i = snmp_node_insert(snmptoolctx, oid2str)) <= 0) { 818216295Ssyrinx free(string); 819216295Ssyrinx free(oid2str); 820216295Ssyrinx } 821216295Ssyrinx return (snmp_import_object(snmptoolctx)); 822216295Ssyrinx 823216295Ssyrinx case ':': 824216295Ssyrinx if (snmp_suboid_append(¤t_oid, (asn_subid_t) val) < 0) 825216295Ssyrinx goto error; 826216295Ssyrinx if (snmp_import_table(snmptoolctx, oid2str) < 0) 827216295Ssyrinx goto error; 828216295Ssyrinx /* 829216295Ssyrinx * A different table entry type was malloced and the data is 830216295Ssyrinx * contained there. 831216295Ssyrinx */ 832216295Ssyrinx free(oid2str); 833216295Ssyrinx return (1); 834216295Ssyrinx 835216295Ssyrinx case TOK_TYPE: 836216295Ssyrinx /* FALLTHROUGH */ 837216295Ssyrinx case TOK_DEFTYPE: 838216295Ssyrinx /* FALLTHROUGH */ 839216295Ssyrinx case TOK_ENUM: 840216295Ssyrinx /* FALLTHROUGH */ 841216295Ssyrinx case TOK_BITS: 842216295Ssyrinx if (snmp_import_leaf(snmptoolctx, &tok, oid2str) < 0) 843216295Ssyrinx goto error; 844216295Ssyrinx return (1); 845216295Ssyrinx 846216295Ssyrinx default: 847216295Ssyrinx warnx("Unexpected token at line %d - %s", input->lno, 848216295Ssyrinx input->fname); 849216295Ssyrinx break; 850216295Ssyrinx } 851216295Ssyrinx 852216295Ssyrinxerror: 853216295Ssyrinx snmp_mapping_entryfree(oid2str); 854216295Ssyrinx 855216295Ssyrinx return (-1); 856216295Ssyrinx} 857216295Ssyrinx 858216295Ssyrinxstatic int32_t 859216295Ssyrinxsnmp_import_tree(struct snmp_toolinfo *snmptoolctx, enum tok *tok) 860216295Ssyrinx{ 861216295Ssyrinx while (*tok != TOK_EOF) { 862216295Ssyrinx switch (*tok) { 863216295Ssyrinx case TOK_ERR: 864216295Ssyrinx return (-1); 865216295Ssyrinx case '(': 866216295Ssyrinx if (snmp_import_object(snmptoolctx) < 0) 867216295Ssyrinx return (-1); 868216295Ssyrinx break; 869216295Ssyrinx case ')': 870216295Ssyrinx if (snmp_suboid_pop(¤t_oid) < 0) 871216295Ssyrinx return (-1); 872216295Ssyrinx (void) snmp_import_update_table(ENTRY_NONE, NULL); 873216295Ssyrinx break; 874216295Ssyrinx default: 875216295Ssyrinx /* Anything else here would be illegal. */ 876216295Ssyrinx return (-1); 877216295Ssyrinx } 878216295Ssyrinx *tok = gettoken(snmptoolctx); 879216295Ssyrinx } 880216295Ssyrinx 881216295Ssyrinx return (0); 882216295Ssyrinx} 883216295Ssyrinx 884216295Ssyrinxstatic int32_t 885216295Ssyrinxsnmp_import_top(struct snmp_toolinfo *snmptoolctx, enum tok *tok) 886216295Ssyrinx{ 887216295Ssyrinx enum snmp_tc tc; 888216295Ssyrinx struct enum_type *t; 889216295Ssyrinx 890216295Ssyrinx if (*tok == '(') 891216295Ssyrinx return (snmp_import_tree(snmptoolctx, tok)); 892216295Ssyrinx 893216295Ssyrinx if (*tok == TOK_TYPEDEF) { 894216295Ssyrinx if ((*tok = gettoken(snmptoolctx)) != TOK_STR) { 895216295Ssyrinx warnx("type name expected after typedef - %s", 896216295Ssyrinx input->fname); 897216295Ssyrinx return (-1); 898216295Ssyrinx } 899216295Ssyrinx 900216295Ssyrinx t = snmp_enumtc_init(nexttok); 901216295Ssyrinx 902216295Ssyrinx *tok = gettoken(snmptoolctx); 903216295Ssyrinx t->is_enum = (*tok == TOK_ENUM); 904216295Ssyrinx t->is_bits = (*tok == TOK_BITS); 905216295Ssyrinx t->syntax = parse_type(snmptoolctx, tok, &tc, &(t->snmp_enum)); 906216295Ssyrinx snmp_enumtc_insert(snmptoolctx, t); 907216295Ssyrinx 908216295Ssyrinx return (1); 909216295Ssyrinx } 910216295Ssyrinx 911216295Ssyrinx if (*tok == TOK_INCLUDE) { 912216295Ssyrinx int i; 913216295Ssyrinx 914216295Ssyrinx *tok = gettoken(snmptoolctx); 915216295Ssyrinx if (*tok != TOK_FILENAME) { 916216295Ssyrinx warnx("filename expected in include directive - %s", 917216295Ssyrinx nexttok); 918216295Ssyrinx return (-1); 919216295Ssyrinx } 920216295Ssyrinx 921216295Ssyrinx if (( i = add_filename(snmptoolctx, nexttok, NULL, 1)) == 0) { 922216295Ssyrinx *tok = gettoken(snmptoolctx); 923216295Ssyrinx return (1); 924216295Ssyrinx } 925216295Ssyrinx 926216295Ssyrinx if (i == -1) 927216295Ssyrinx return (-1); 928216295Ssyrinx 929216295Ssyrinx input_fopen(nexttok); 930216295Ssyrinx *tok = gettoken(snmptoolctx); 931216295Ssyrinx return (1); 932216295Ssyrinx } 933216295Ssyrinx 934216295Ssyrinx warnx("'(' or 'typedef' expected - %s", nexttok); 935216295Ssyrinx return (-1); 936216295Ssyrinx} 937216295Ssyrinx 938216295Ssyrinxstatic int32_t 939216295Ssyrinxsnmp_import(struct snmp_toolinfo *snmptoolctx) 940216295Ssyrinx{ 941216295Ssyrinx int i; 942216295Ssyrinx enum tok tok; 943216295Ssyrinx 944216295Ssyrinx tok = gettoken(snmptoolctx); 945216295Ssyrinx 946216295Ssyrinx do 947216295Ssyrinx i = snmp_import_top(snmptoolctx, &tok); 948216295Ssyrinx while (i > 0); 949216295Ssyrinx 950216295Ssyrinx return (i); 951216295Ssyrinx} 952216295Ssyrinx 953216295Ssyrinx/* 954216295Ssyrinx * Read a .def file and import oid<->string mapping. 955216295Ssyrinx * Mappings are inserted into a global structure containing list for each OID 956216295Ssyrinx * syntax type. 957216295Ssyrinx */ 958216295Ssyrinxint32_t 959216295Ssyrinxsnmp_import_file(struct snmp_toolinfo *snmptoolctx, struct fname *file) 960216295Ssyrinx{ 961216295Ssyrinx int idx; 962216295Ssyrinx 963216295Ssyrinx snmp_import_init(&(file->cut)); 964216295Ssyrinx input_fopen(file->name); 965216295Ssyrinx if ((idx = snmp_import(snmptoolctx)) < 0) 966216295Ssyrinx warnx("Failed to read mappings from file %s", file->name); 967216295Ssyrinx 968216295Ssyrinx input_close(); 969216295Ssyrinx 970216295Ssyrinx return (idx); 971216295Ssyrinx} 972