gensnmptree.c revision 133211
1122394Sharti/* 2122394Sharti * Copyright (c) 2001-2003 3122394Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4122394Sharti * All rights reserved. 5122394Sharti * 6133211Sharti * Copyright (c) 2004 7133211Sharti * Hartmut Brandt. 8133211Sharti * All rights reserved. 9133211Sharti * 10122394Sharti * Author: Harti Brandt <harti@freebsd.org> 11133211Sharti * 12133211Sharti * Redistribution and use in source and binary forms, with or without 13133211Sharti * modification, are permitted provided that the following conditions 14133211Sharti * are met: 15133211Sharti * 1. Redistributions of source code must retain the above copyright 16133211Sharti * notice, this list of conditions and the following disclaimer. 17122394Sharti * 2. Redistributions in binary form must reproduce the above copyright 18122394Sharti * notice, this list of conditions and the following disclaimer in the 19122394Sharti * documentation and/or other materials provided with the distribution. 20133211Sharti * 21133211Sharti * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 22133211Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23133211Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24133211Sharti * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 25133211Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26133211Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27133211Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28133211Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29133211Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30133211Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31133211Sharti * SUCH DAMAGE. 32122394Sharti * 33133211Sharti * $Begemot: bsnmp/gensnmptree/gensnmptree.c,v 1.38 2004/08/06 08:46:46 brandt Exp $ 34122394Sharti * 35122394Sharti * Generate OID table from table description. 36122394Sharti * 37122394Sharti * Syntax is: 38122394Sharti * --------- 39133211Sharti * file := tree | tree file 40133211Sharti * 41122394Sharti * tree := head elements ')' 42122394Sharti * 43122394Sharti * entry := head ':' index STRING elements ')' 44122394Sharti * 45122394Sharti * leaf := head TYPE STRING ACCESS ')' 46122394Sharti * 47122394Sharti * column := head TYPE ACCESS ')' 48122394Sharti * 49122394Sharti * head := '(' INT STRING 50122394Sharti * 51122394Sharti * elements := EMPTY | elements element 52122394Sharti * 53122394Sharti * element := tree | leaf 54122394Sharti * 55122394Sharti * index := TYPE | index TYPE 56122394Sharti * 57122394Sharti */ 58122394Sharti#include <sys/types.h> 59122394Sharti#include <sys/param.h> 60122394Sharti#include <stdio.h> 61122394Sharti#include <stdlib.h> 62122394Sharti#include <stdarg.h> 63122394Sharti#include <unistd.h> 64122394Sharti#include <string.h> 65122394Sharti#include <ctype.h> 66133211Sharti#include <stdint.h> 67133211Sharti#include <errno.h> 68133211Sharti#ifdef HAVE_ERR_H 69122394Sharti#include <err.h> 70133211Sharti#endif 71122394Sharti#include <sys/queue.h> 72133211Sharti#include "support.h" 73122394Sharti#include "asn1.h" 74122394Sharti#include "snmp.h" 75122394Sharti#include "snmpagent.h" 76122394Sharti 77122394Sharti/* 78122394Sharti * Constant prefix for all OIDs 79122394Sharti */ 80122394Shartistatic const asn_subid_t prefix[] = { 1, 3, 6 }; 81122394Sharti#define PREFIX_LEN (sizeof(prefix) / sizeof(prefix[0])) 82122394Sharti 83122394Shartiu_int tree_size; 84122394Shartistatic const char *file_prefix = ""; 85122394Shartistatic FILE *fp; 86122394Sharti 87122394Sharti/* if true generate local include paths */ 88122394Shartistatic int localincs = 0; 89122394Sharti 90122394Shartistatic const char usgtxt[] = "\ 91122394ShartiGenerate SNMP tables. Copyright (c) 2001-2002 Fraunhofer Institute for\n\ 92122394ShartiOpen Communication Systems (FhG Fokus). All rights reserved.\n\ 93122394Shartiusage: gensnmptree [-hel] [-p prefix] [name]...\n\ 94122394Shartioptions:\n\ 95122394Sharti -h print this info\n\ 96122394Sharti -e extrace the named oids\n\ 97122394Sharti -l generate local include directives\n\ 98122394Sharti -p prefix prepend prefix to file and variable names\n\ 99122394Sharti"; 100122394Sharti 101122394Sharti/* 102122394Sharti * A node in the OID tree 103122394Sharti */ 104122394Shartienum ntype { 105122394Sharti NODE_LEAF = 1, 106122394Sharti NODE_TREE, 107122394Sharti NODE_ENTRY, 108122394Sharti NODE_COLUMN 109122394Sharti}; 110122394Sharti 111122394Shartienum { 112122394Sharti FL_GET = 0x01, 113122394Sharti FL_SET = 0x02, 114122394Sharti}; 115122394Sharti 116122394Shartistruct node; 117122394ShartiTAILQ_HEAD(node_list, node); 118122394Sharti 119122394Shartistruct node { 120122394Sharti enum ntype type; 121122394Sharti asn_subid_t id; /* last element of OID */ 122122394Sharti char *name; /* name of node */ 123122394Sharti TAILQ_ENTRY(node) link; 124122394Sharti u_int lno; /* starting line number */ 125122394Sharti u_int flags; /* allowed operations */ 126122394Sharti 127122394Sharti union { 128122394Sharti struct tree { 129122394Sharti struct node_list subs; 130122394Sharti } tree; 131122394Sharti 132122394Sharti struct entry { 133133211Sharti uint32_t index; /* index for table entry */ 134122394Sharti char *func; /* function for tables */ 135122394Sharti struct node_list subs; 136122394Sharti } entry; 137122394Sharti 138122394Sharti struct leaf { 139122394Sharti enum snmp_syntax syntax; /* syntax for this leaf */ 140122394Sharti char *func; /* function name */ 141122394Sharti } leaf; 142122394Sharti 143122394Sharti struct column { 144122394Sharti enum snmp_syntax syntax; /* syntax for this column */ 145122394Sharti } column; 146122394Sharti } u; 147122394Sharti}; 148122394Sharti 149122394Shartistruct func { 150122394Sharti const char *name; 151122394Sharti LIST_ENTRY(func) link; 152122394Sharti}; 153122394Sharti 154122394Shartistatic LIST_HEAD(, func) funcs = LIST_HEAD_INITIALIZER(funcs); 155122394Sharti 156122394Sharti/************************************************************ 157122394Sharti * 158122394Sharti * Allocate memory and panic just in the case... 159122394Sharti */ 160122394Shartistatic void * 161122394Shartixalloc(size_t size) 162122394Sharti{ 163122394Sharti void *ptr; 164122394Sharti 165122394Sharti if ((ptr = malloc(size)) == NULL) 166122394Sharti err(1, "allocing %u bytes", size); 167122394Sharti 168122394Sharti return (ptr); 169122394Sharti} 170122394Sharti 171122394Sharti/************************************************************ 172122394Sharti * 173122394Sharti * Parsing input 174122394Sharti */ 175122394Shartienum tok { 176122394Sharti TOK_EOF = 0200, /* end-of-file seen */ 177122394Sharti TOK_NUM, /* number */ 178122394Sharti TOK_STR, /* string */ 179122394Sharti TOK_ACCESS, /* access operator */ 180122394Sharti TOK_TYPE, /* type operator */ 181122394Sharti}; 182122394Sharti 183122394Shartistatic const struct { 184122394Sharti const char *str; 185122394Sharti enum tok tok; 186122394Sharti u_int val; 187122394Sharti} keywords[] = { 188122394Sharti { "GET", TOK_ACCESS, FL_GET }, 189122394Sharti { "SET", TOK_ACCESS, FL_SET }, 190122394Sharti { "NULL", TOK_TYPE, SNMP_SYNTAX_NULL }, 191122394Sharti { "INTEGER", TOK_TYPE, SNMP_SYNTAX_INTEGER }, 192122394Sharti { "INTEGER32", TOK_TYPE, SNMP_SYNTAX_INTEGER }, 193122394Sharti { "UNSIGNED32", TOK_TYPE, SNMP_SYNTAX_GAUGE }, 194122394Sharti { "OCTETSTRING", TOK_TYPE, SNMP_SYNTAX_OCTETSTRING }, 195122394Sharti { "IPADDRESS", TOK_TYPE, SNMP_SYNTAX_IPADDRESS }, 196122394Sharti { "OID", TOK_TYPE, SNMP_SYNTAX_OID }, 197122394Sharti { "TIMETICKS", TOK_TYPE, SNMP_SYNTAX_TIMETICKS }, 198122394Sharti { "COUNTER", TOK_TYPE, SNMP_SYNTAX_COUNTER }, 199122394Sharti { "GAUGE", TOK_TYPE, SNMP_SYNTAX_GAUGE }, 200122394Sharti { "COUNTER64", TOK_TYPE, SNMP_SYNTAX_COUNTER64 }, 201122394Sharti { NULL, 0, 0 } 202122394Sharti}; 203122394Sharti 204122394Sharti/* arbitrary upper limit on node names and function names */ 205122394Sharti#define MAXSTR 1000 206122394Shartichar str[MAXSTR]; 207122394Shartiu_long val; /* integer values */ 208122394Shartiu_int lno = 1; /* current line number */ 209133211Shartiint all_cond; /* all conditions are true */ 210122394Sharti 211122394Shartistatic void report(const char *, ...) __dead2 __printflike(1, 2); 212122394Shartistatic void report_node(const struct node *, const char *, ...) 213122394Sharti __dead2 __printflike(2, 3); 214122394Sharti 215122394Sharti/* 216122394Sharti * Report an error and exit. 217122394Sharti */ 218122394Shartistatic void 219122394Shartireport(const char *fmt, ...) 220122394Sharti{ 221122394Sharti va_list ap; 222122394Sharti int c; 223122394Sharti 224122394Sharti va_start(ap, fmt); 225122394Sharti fprintf(stderr, "line %u: ", lno); 226122394Sharti vfprintf(stderr, fmt, ap); 227122394Sharti fprintf(stderr, "\n"); 228122394Sharti fprintf(stderr, "context: \""); 229122394Sharti while ((c = getchar()) != EOF && c != '\n') 230122394Sharti fprintf(stderr, "%c", c); 231122394Sharti fprintf(stderr, "\n"); 232122394Sharti va_end(ap); 233122394Sharti exit(1); 234122394Sharti} 235122394Shartistatic void 236122394Shartireport_node(const struct node *np, const char *fmt, ...) 237122394Sharti{ 238122394Sharti va_list ap; 239122394Sharti 240122394Sharti va_start(ap, fmt); 241122394Sharti fprintf(stderr, "line %u, node %s: ", np->lno, np->name); 242122394Sharti vfprintf(stderr, fmt, ap); 243122394Sharti fprintf(stderr, "\n"); 244122394Sharti va_end(ap); 245122394Sharti exit(1); 246122394Sharti} 247122394Sharti 248122394Sharti/* 249122394Sharti * Return a fresh copy of the string constituting the current token. 250122394Sharti */ 251122394Shartistatic char * 252122394Shartisavetok(void) 253122394Sharti{ 254122394Sharti return (strcpy(xalloc(strlen(str)+1), str)); 255122394Sharti} 256122394Sharti 257122394Sharti/* 258122394Sharti * Get the next token from input. 259122394Sharti */ 260122394Shartistatic int 261122394Shartigettoken(void) 262122394Sharti{ 263122394Sharti int c; 264122394Sharti 265122394Sharti again: 266122394Sharti /* 267122394Sharti * Skip any whitespace before the next token 268122394Sharti */ 269122394Sharti while ((c = getchar()) != EOF) { 270122394Sharti if (c == '\n') 271122394Sharti lno++; 272122394Sharti if (!isspace(c)) 273122394Sharti break; 274122394Sharti } 275122394Sharti if (c == EOF) 276122394Sharti return (TOK_EOF); 277122394Sharti if (!isascii(c)) 278122394Sharti report("unexpected character %#2x", (u_int)c); 279122394Sharti 280122394Sharti /* 281122394Sharti * Skip comments 282122394Sharti */ 283122394Sharti if (c == '#') { 284122394Sharti while ((c = getchar()) != EOF) { 285122394Sharti if (c == '\n') { 286122394Sharti lno++; 287122394Sharti goto again; 288122394Sharti } 289122394Sharti } 290122394Sharti report("unexpected EOF in comment"); 291122394Sharti } 292122394Sharti 293122394Sharti /* 294122394Sharti * Single character tokens 295122394Sharti */ 296122394Sharti if (c == ')' || c == '(' || c == ':') 297122394Sharti return (c); 298122394Sharti 299122394Sharti /* 300122394Sharti * Sort out numbers 301122394Sharti */ 302122394Sharti if (isdigit(c)) { 303122394Sharti ungetc(c, stdin); 304122394Sharti scanf("%lu", &val); 305122394Sharti return (TOK_NUM); 306122394Sharti } 307122394Sharti 308122394Sharti /* 309122394Sharti * So that has to be a string. 310122394Sharti */ 311122394Sharti if (isalpha(c) || c == '_') { 312122394Sharti size_t n = 0; 313122394Sharti str[n++] = c; 314122394Sharti while ((c = getchar()) != EOF) { 315122394Sharti if (!isalnum(c) && c != '_') { 316122394Sharti ungetc(c, stdin); 317122394Sharti break; 318122394Sharti } 319122394Sharti if (n == sizeof(str) - 1) { 320122394Sharti str[n++] = '\0'; 321122394Sharti report("string too long '%s...'", str); 322122394Sharti } 323122394Sharti str[n++] = c; 324122394Sharti } 325122394Sharti str[n++] = '\0'; 326122394Sharti 327122394Sharti /* 328122394Sharti * Keywords 329122394Sharti */ 330122394Sharti for (c = 0; keywords[c].str != NULL; c++) 331122394Sharti if (strcmp(keywords[c].str, str) == 0) { 332122394Sharti val = keywords[c].val; 333122394Sharti return (keywords[c].tok); 334122394Sharti } 335122394Sharti 336122394Sharti return (TOK_STR); 337122394Sharti } 338122394Sharti if (isprint(c)) 339122394Sharti errx(1, "%u: unexpected character '%c'", lno, c); 340122394Sharti else 341122394Sharti errx(1, "%u: unexpected character 0x%02x", lno, (u_int)c); 342122394Sharti} 343122394Sharti 344122394Sharti/* 345122394Sharti * Parse the next node (complete with all subnodes) 346122394Sharti */ 347122394Shartistatic struct node * 348122394Shartiparse(enum tok tok) 349122394Sharti{ 350122394Sharti struct node *node; 351122394Sharti struct node *sub; 352122394Sharti u_int index_count; 353122394Sharti 354122394Sharti node = xalloc(sizeof(struct node)); 355122394Sharti node->lno = lno; 356122394Sharti 357122394Sharti if (tok != '(') 358122394Sharti report("'(' expected at begin of node"); 359122394Sharti if (gettoken() != TOK_NUM) 360122394Sharti report("node id expected after opening '('"); 361122394Sharti if (val > ASN_MAXID) 362122394Sharti report("subid too large '%lu'", val); 363122394Sharti node->id = (asn_subid_t)val; 364122394Sharti if (gettoken() != TOK_STR) 365122394Sharti report("node name expected after '(' ID"); 366122394Sharti node->name = savetok(); 367122394Sharti 368122394Sharti if ((tok = gettoken()) == TOK_TYPE) { 369122394Sharti /* LEAF or COLUM */ 370122394Sharti u_int syntax = val; 371122394Sharti 372122394Sharti if ((tok = gettoken()) == TOK_STR) { 373122394Sharti /* LEAF */ 374122394Sharti node->type = NODE_LEAF; 375122394Sharti node->u.leaf.func = savetok(); 376122394Sharti node->u.leaf.syntax = syntax; 377122394Sharti tok = gettoken(); 378122394Sharti } else { 379122394Sharti /* COLUMN */ 380122394Sharti node->type = NODE_COLUMN; 381122394Sharti node->u.column.syntax = syntax; 382122394Sharti } 383122394Sharti 384122394Sharti while (tok != ')') { 385122394Sharti if (tok != TOK_ACCESS) 386122394Sharti report("access keyword or ')' expected"); 387122394Sharti node->flags |= (u_int)val; 388122394Sharti tok = gettoken(); 389122394Sharti } 390122394Sharti 391122394Sharti } else if (tok == ':') { 392122394Sharti /* ENTRY */ 393122394Sharti node->type = NODE_ENTRY; 394122394Sharti TAILQ_INIT(&node->u.entry.subs); 395122394Sharti 396122394Sharti index_count = 0; 397122394Sharti node->u.entry.index = 0; 398122394Sharti while ((tok = gettoken()) == TOK_TYPE) { 399122394Sharti if (index_count++ == SNMP_INDEXES_MAX) 400122394Sharti report("too many table indexes"); 401122394Sharti node->u.entry.index |= 402122394Sharti val << (SNMP_INDEX_SHIFT * index_count); 403122394Sharti } 404122394Sharti node->u.entry.index |= index_count; 405122394Sharti if (index_count == 0) 406122394Sharti report("need at least one index"); 407122394Sharti 408122394Sharti if (tok != TOK_STR) 409122394Sharti report("function name expected"); 410122394Sharti 411122394Sharti node->u.entry.func = savetok(); 412122394Sharti 413122394Sharti tok = gettoken(); 414122394Sharti 415122394Sharti while (tok != ')') { 416122394Sharti sub = parse(tok); 417122394Sharti TAILQ_INSERT_TAIL(&node->u.entry.subs, sub, link); 418122394Sharti tok = gettoken(); 419122394Sharti } 420122394Sharti 421122394Sharti } else { 422122394Sharti /* subtree */ 423122394Sharti node->type = NODE_TREE; 424122394Sharti TAILQ_INIT(&node->u.tree.subs); 425122394Sharti 426122394Sharti while (tok != ')') { 427122394Sharti sub = parse(tok); 428122394Sharti TAILQ_INSERT_TAIL(&node->u.tree.subs, sub, link); 429122394Sharti tok = gettoken(); 430122394Sharti } 431122394Sharti } 432122394Sharti return (node); 433122394Sharti} 434122394Sharti 435122394Sharti/* 436122394Sharti * Generate the C-code table part for one node. 437122394Sharti */ 438122394Shartistatic void 439122394Shartigen_node(struct node *np, struct asn_oid *oid, u_int idx, const char *func) 440122394Sharti{ 441122394Sharti u_int n; 442122394Sharti struct node *sub; 443122394Sharti u_int syntax; 444122394Sharti 445122394Sharti if (oid->len == ASN_MAXOIDLEN) 446122394Sharti report_node(np, "OID too long"); 447122394Sharti oid->subs[oid->len++] = np->id; 448122394Sharti 449122394Sharti if (np->type == NODE_TREE) { 450122394Sharti TAILQ_FOREACH(sub, &np->u.tree.subs, link) 451122394Sharti gen_node(sub, oid, 0, NULL); 452122394Sharti oid->len--; 453122394Sharti return; 454122394Sharti } 455122394Sharti if (np->type == NODE_ENTRY) { 456122394Sharti TAILQ_FOREACH(sub, &np->u.entry.subs, link) 457122394Sharti gen_node(sub, oid, np->u.entry.index, np->u.entry.func); 458122394Sharti oid->len--; 459122394Sharti return; 460122394Sharti } 461122394Sharti 462122394Sharti /* leaf or column */ 463122394Sharti if ((np->flags & (FL_GET|FL_SET)) == 0) { 464122394Sharti oid->len--; 465122394Sharti return; 466122394Sharti } 467122394Sharti 468122394Sharti fprintf(fp, " {{ %u, {", oid->len); 469122394Sharti for (n = 0; n < oid->len; n++) 470122394Sharti fprintf(fp, " %u,", oid->subs[n]); 471122394Sharti fprintf(fp, " }}, \"%s\", ", np->name); 472122394Sharti 473122394Sharti if (np->type == NODE_COLUMN) { 474122394Sharti syntax = np->u.column.syntax; 475122394Sharti fprintf(fp, "SNMP_NODE_COLUMN, "); 476122394Sharti } else { 477122394Sharti syntax = np->u.leaf.syntax; 478122394Sharti fprintf(fp, "SNMP_NODE_LEAF, "); 479122394Sharti } 480122394Sharti 481122394Sharti switch (syntax) { 482122394Sharti 483122394Sharti case SNMP_SYNTAX_NULL: 484122394Sharti fprintf(fp, "SNMP_SYNTAX_NULL, "); 485122394Sharti break; 486122394Sharti 487122394Sharti case SNMP_SYNTAX_INTEGER: 488122394Sharti fprintf(fp, "SNMP_SYNTAX_INTEGER, "); 489122394Sharti break; 490122394Sharti 491122394Sharti case SNMP_SYNTAX_OCTETSTRING: 492122394Sharti fprintf(fp, "SNMP_SYNTAX_OCTETSTRING, "); 493122394Sharti break; 494122394Sharti 495122394Sharti case SNMP_SYNTAX_IPADDRESS: 496122394Sharti fprintf(fp, "SNMP_SYNTAX_IPADDRESS, "); 497122394Sharti break; 498122394Sharti 499122394Sharti case SNMP_SYNTAX_OID: 500122394Sharti fprintf(fp, "SNMP_SYNTAX_OID, "); 501122394Sharti break; 502122394Sharti 503122394Sharti case SNMP_SYNTAX_TIMETICKS: 504122394Sharti fprintf(fp, "SNMP_SYNTAX_TIMETICKS, "); 505122394Sharti break; 506122394Sharti 507122394Sharti case SNMP_SYNTAX_COUNTER: 508122394Sharti fprintf(fp, "SNMP_SYNTAX_COUNTER, "); 509122394Sharti break; 510122394Sharti 511122394Sharti case SNMP_SYNTAX_GAUGE: 512122394Sharti fprintf(fp, "SNMP_SYNTAX_GAUGE, "); 513122394Sharti break; 514122394Sharti 515122394Sharti case SNMP_SYNTAX_COUNTER64: 516122394Sharti fprintf(fp, "SNMP_SYNTAX_COUNTER64, "); 517122394Sharti break; 518122394Sharti 519122394Sharti case SNMP_SYNTAX_NOSUCHOBJECT: 520122394Sharti case SNMP_SYNTAX_NOSUCHINSTANCE: 521122394Sharti case SNMP_SYNTAX_ENDOFMIBVIEW: 522122394Sharti abort(); 523122394Sharti } 524122394Sharti 525122394Sharti if (np->type == NODE_COLUMN) 526122394Sharti fprintf(fp, "%s, ", func); 527122394Sharti else 528122394Sharti fprintf(fp, "%s, ", np->u.leaf.func); 529122394Sharti 530122394Sharti fprintf(fp, "0"); 531122394Sharti if (np->flags & FL_SET) 532122394Sharti fprintf(fp, "|SNMP_NODE_CANSET"); 533128237Sharti fprintf(fp, ", %#x, NULL, NULL },\n", idx); 534122394Sharti oid->len--; 535122394Sharti return; 536122394Sharti} 537122394Sharti 538122394Sharti/* 539122394Sharti * Generate the header file with the function declarations. 540122394Sharti */ 541122394Shartistatic void 542122394Shartigen_header(struct node *np, u_int oidlen, const char *func) 543122394Sharti{ 544122394Sharti char f[MAXSTR + 4]; 545122394Sharti struct node *sub; 546122394Sharti struct func *ptr; 547122394Sharti 548122394Sharti oidlen++; 549122394Sharti if (np->type == NODE_TREE) { 550122394Sharti TAILQ_FOREACH(sub, &np->u.tree.subs, link) 551122394Sharti gen_header(sub, oidlen, NULL); 552122394Sharti return; 553122394Sharti } 554122394Sharti if (np->type == NODE_ENTRY) { 555122394Sharti TAILQ_FOREACH(sub, &np->u.entry.subs, link) 556122394Sharti gen_header(sub, oidlen, np->u.entry.func); 557122394Sharti return; 558122394Sharti } 559122394Sharti 560122394Sharti if((np->flags & (FL_GET|FL_SET)) == 0) 561122394Sharti return; 562122394Sharti 563122394Sharti if (np->type == NODE_COLUMN) 564122394Sharti sprintf(f, "%s", func); 565122394Sharti else 566122394Sharti sprintf(f, "%s", np->u.leaf.func); 567122394Sharti 568122394Sharti LIST_FOREACH(ptr, &funcs, link) 569122394Sharti if (strcmp(ptr->name, f) == 0) 570122394Sharti break; 571122394Sharti 572122394Sharti if (ptr == NULL) { 573122394Sharti ptr = xalloc(sizeof(*ptr)); 574122394Sharti ptr->name = strcpy(xalloc(strlen(f)+1), f); 575122394Sharti LIST_INSERT_HEAD(&funcs, ptr, link); 576122394Sharti 577122394Sharti fprintf(fp, "int %s(struct snmp_context *, " 578122394Sharti "struct snmp_value *, u_int, u_int, " 579122394Sharti "enum snmp_op);\n", f); 580122394Sharti } 581122394Sharti 582122394Sharti fprintf(fp, "# define LEAF_%s %u\n", np->name, np->id); 583122394Sharti} 584122394Sharti 585122394Sharti/* 586122394Sharti * Generate the OID table. 587122394Sharti */ 588122394Shartistatic void 589122394Shartigen_table(struct node *node) 590122394Sharti{ 591122394Sharti struct asn_oid oid; 592122394Sharti 593122394Sharti fprintf(fp, "#include <sys/types.h>\n"); 594122394Sharti fprintf(fp, "#include <stdio.h>\n"); 595133211Sharti fprintf(fp, "#include <stdint.h>\n"); 596122394Sharti if (localincs) { 597122394Sharti fprintf(fp, "#include \"asn1.h\"\n"); 598122394Sharti fprintf(fp, "#include \"snmp.h\"\n"); 599122394Sharti fprintf(fp, "#include \"snmpagent.h\"\n"); 600122394Sharti } else { 601122394Sharti fprintf(fp, "#include <bsnmp/asn1.h>\n"); 602122394Sharti fprintf(fp, "#include <bsnmp/snmp.h>\n"); 603122394Sharti fprintf(fp, "#include <bsnmp/snmpagent.h>\n"); 604122394Sharti } 605122394Sharti fprintf(fp, "#include \"%stree.h\"\n", file_prefix); 606122394Sharti fprintf(fp, "\n"); 607122394Sharti 608122394Sharti fprintf(fp, "const struct snmp_node %sctree[] = {\n", file_prefix); 609122394Sharti 610122394Sharti oid.len = PREFIX_LEN; 611122394Sharti memcpy(oid.subs, prefix, sizeof(prefix)); 612122394Sharti gen_node(node, &oid, 0, NULL); 613122394Sharti 614122394Sharti fprintf(fp, "};\n\n"); 615122394Sharti} 616122394Sharti 617133211Shartistatic void 618133211Shartiprint_syntax(u_int syntax) 619133211Sharti{ 620133211Sharti u_int i; 621133211Sharti 622133211Sharti for (i = 0; keywords[i].str != NULL; i++) 623133211Sharti if (keywords[i].tok == TOK_TYPE && 624133211Sharti keywords[i].val == syntax) { 625133211Sharti printf(" %s", keywords[i].str); 626133211Sharti return; 627133211Sharti } 628133211Sharti abort(); 629133211Sharti} 630133211Sharti 631133211Sharti/* 632133211Sharti * Generate a tree definition file 633133211Sharti */ 634133211Shartistatic void 635133211Shartigen_tree(const struct node *np, int level) 636133211Sharti{ 637133211Sharti const struct node *sp; 638133211Sharti u_int i; 639133211Sharti 640133211Sharti printf("%*s(%u %s", 2 * level, "", np->id, np->name); 641133211Sharti 642133211Sharti switch (np->type) { 643133211Sharti 644133211Sharti case NODE_LEAF: 645133211Sharti print_syntax(np->u.leaf.syntax); 646133211Sharti printf(" %s%s%s)\n", np->u.leaf.func, 647133211Sharti (np->flags & FL_GET) ? " GET" : "", 648133211Sharti (np->flags & FL_SET) ? " SET" : ""); 649133211Sharti break; 650133211Sharti 651133211Sharti case NODE_TREE: 652133211Sharti if (TAILQ_EMPTY(&np->u.tree.subs)) { 653133211Sharti printf(")\n"); 654133211Sharti } else { 655133211Sharti printf("\n"); 656133211Sharti TAILQ_FOREACH(sp, &np->u.tree.subs, link) 657133211Sharti gen_tree(sp, level + 1); 658133211Sharti printf("%*s)\n", 2 * level, ""); 659133211Sharti } 660133211Sharti break; 661133211Sharti 662133211Sharti case NODE_ENTRY: 663133211Sharti printf(" :"); 664133211Sharti 665133211Sharti for (i = 0; i < SNMP_INDEX_COUNT(np->u.entry.index); i++) 666133211Sharti print_syntax(SNMP_INDEX(np->u.entry.index, i)); 667133211Sharti printf(" %s\n", np->u.entry.func); 668133211Sharti TAILQ_FOREACH(sp, &np->u.entry.subs, link) 669133211Sharti gen_tree(sp, level + 1); 670133211Sharti printf("%*s)\n", 2 * level, ""); 671133211Sharti break; 672133211Sharti 673133211Sharti case NODE_COLUMN: 674133211Sharti print_syntax(np->u.column.syntax); 675133211Sharti printf("%s%s)\n", (np->flags & FL_GET) ? " GET" : "", 676133211Sharti (np->flags & FL_SET) ? " SET" : ""); 677133211Sharti break; 678133211Sharti 679133211Sharti } 680133211Sharti} 681133211Sharti 682122394Shartistatic int 683133211Shartiextract(const struct node *np, struct asn_oid *oid, const char *obj, 684133211Sharti const struct asn_oid *idx, const char *iname) 685122394Sharti{ 686122394Sharti struct node *sub; 687122394Sharti u_long n; 688122394Sharti 689122394Sharti if (oid->len == ASN_MAXOIDLEN) 690122394Sharti report_node(np, "OID too long"); 691122394Sharti oid->subs[oid->len++] = np->id; 692122394Sharti 693122394Sharti if (strcmp(obj, np->name) == 0) { 694133211Sharti if (oid->len + idx->len >= ASN_MAXOIDLEN) 695133211Sharti report_node(np, "OID too long"); 696133211Sharti fprintf(fp, "#define OID_%s%s\t%u\n", np->name, 697133211Sharti iname ? iname : "", np->id); 698133211Sharti fprintf(fp, "#define OIDLEN_%s%s\t%u\n", np->name, 699133211Sharti iname ? iname : "", oid->len + idx->len); 700133211Sharti fprintf(fp, "#define OIDX_%s%s\t{ %u, {", np->name, 701133211Sharti iname ? iname : "", oid->len + idx->len); 702122394Sharti for (n = 0; n < oid->len; n++) 703122394Sharti fprintf(fp, " %u,", oid->subs[n]); 704133211Sharti for (n = 0; n < idx->len; n++) 705133211Sharti fprintf(fp, " %u,", idx->subs[n]); 706122394Sharti fprintf(fp, " } }\n"); 707122394Sharti return (0); 708122394Sharti } 709122394Sharti 710122394Sharti if (np->type == NODE_TREE) { 711122394Sharti TAILQ_FOREACH(sub, &np->u.tree.subs, link) 712133211Sharti if (!extract(sub, oid, obj, idx, iname)) 713122394Sharti return (0); 714122394Sharti } else if (np->type == NODE_ENTRY) { 715122394Sharti TAILQ_FOREACH(sub, &np->u.entry.subs, link) 716133211Sharti if (!extract(sub, oid, obj, idx, iname)) 717122394Sharti return (0); 718122394Sharti } 719122394Sharti oid->len--; 720122394Sharti return (1); 721122394Sharti} 722122394Sharti 723122394Shartistatic int 724133211Shartigen_extract(const struct node *root, char *object) 725122394Sharti{ 726122394Sharti struct asn_oid oid; 727133211Sharti struct asn_oid idx; 728133211Sharti char *s, *e, *end, *iname; 729133211Sharti u_long ul; 730133211Sharti int ret; 731122394Sharti 732133211Sharti /* look whether the object to extract has an index part */ 733133211Sharti idx.len = 0; 734133211Sharti iname = NULL; 735133211Sharti s = strchr(object, '.'); 736133211Sharti if (s != NULL) { 737133211Sharti iname = malloc(strlen(s) + 1); 738133211Sharti if (iname == NULL) 739133211Sharti err(1, "cannot allocated index"); 740133211Sharti 741133211Sharti strcpy(iname, s); 742133211Sharti for (e = iname; *e != '\0'; e++) 743133211Sharti if (*e == '.') 744133211Sharti *e = '_'; 745133211Sharti 746133211Sharti *s++ = '\0'; 747133211Sharti while (s != NULL) { 748133211Sharti if (*s == '\0') 749133211Sharti errx(1, "bad index syntax"); 750133211Sharti if ((e = strchr(s, '.')) != NULL) 751133211Sharti *e++ = '\0'; 752133211Sharti 753133211Sharti errno = 0; 754133211Sharti ul = strtoul(s, &end, 0); 755133211Sharti if (*end != '\0') 756133211Sharti errx(1, "bad index syntax '%s'", end); 757133211Sharti if (errno != 0) 758133211Sharti err(1, "bad index syntax"); 759133211Sharti 760133211Sharti if (idx.len == ASN_MAXOIDLEN) 761133211Sharti errx(1, "index oid too large"); 762133211Sharti idx.subs[idx.len++] = ul; 763133211Sharti 764133211Sharti s = e; 765133211Sharti } 766133211Sharti } 767133211Sharti 768122394Sharti oid.len = PREFIX_LEN; 769122394Sharti memcpy(oid.subs, prefix, sizeof(prefix)); 770133211Sharti ret = extract(root, &oid, object, &idx, iname); 771133211Sharti if (iname != NULL) 772133211Sharti free(iname); 773133211Sharti 774133211Sharti return (ret); 775122394Sharti} 776122394Sharti 777122394Sharti 778122394Shartistatic void 779122394Sharticheck_sub_order(const struct node *np, const struct node_list *subs) 780122394Sharti{ 781122394Sharti int first; 782122394Sharti const struct node *sub; 783122394Sharti asn_subid_t maxid = 0; 784122394Sharti 785122394Sharti /* ensure, that subids are ordered */ 786122394Sharti first = 1; 787122394Sharti TAILQ_FOREACH(sub, subs, link) { 788122394Sharti if (!first && sub->id <= maxid) 789122394Sharti report_node(np, "subids not ordered at %s", sub->name); 790122394Sharti maxid = sub->id; 791122394Sharti first = 0; 792122394Sharti } 793122394Sharti} 794122394Sharti 795122394Sharti/* 796122394Sharti * Do some sanity checks on the tree definition and do some computations. 797122394Sharti */ 798122394Shartistatic void 799122394Sharticheck_tree(struct node *np) 800122394Sharti{ 801122394Sharti struct node *sub; 802122394Sharti 803122394Sharti if (np->type == NODE_LEAF || np->type == NODE_COLUMN) { 804122394Sharti if ((np->flags & (FL_GET|FL_SET)) != 0) 805122394Sharti tree_size++; 806122394Sharti return; 807122394Sharti } 808122394Sharti 809122394Sharti if (np->type == NODE_ENTRY) { 810122394Sharti check_sub_order(np, &np->u.entry.subs); 811122394Sharti 812122394Sharti /* ensure all subnodes are columns */ 813122394Sharti TAILQ_FOREACH(sub, &np->u.entry.subs, link) { 814122394Sharti if (sub->type != NODE_COLUMN) 815122394Sharti report_node(np, "entry subnode '%s' is not " 816122394Sharti "a column", sub->name); 817122394Sharti check_tree(sub); 818122394Sharti } 819122394Sharti } else { 820122394Sharti check_sub_order(np, &np->u.tree.subs); 821122394Sharti 822122394Sharti TAILQ_FOREACH(sub, &np->u.tree.subs, link) 823122394Sharti check_tree(sub); 824122394Sharti } 825122394Sharti} 826122394Sharti 827133211Shartistatic void 828133211Shartimerge_subs(struct node_list *s1, struct node_list *s2) 829133211Sharti{ 830133211Sharti struct node *n1, *n2; 831133211Sharti 832133211Sharti while (!TAILQ_EMPTY(s2)) { 833133211Sharti n2 = TAILQ_FIRST(s2); 834133211Sharti TAILQ_REMOVE(s2, n2, link); 835133211Sharti 836133211Sharti TAILQ_FOREACH(n1, s1, link) 837133211Sharti if (n1->id >= n2->id) 838133211Sharti break; 839133211Sharti if (n1 == NULL) 840133211Sharti TAILQ_INSERT_TAIL(s1, n2, link); 841133211Sharti else if (n1->id > n2->id) 842133211Sharti TAILQ_INSERT_BEFORE(n1, n2, link); 843133211Sharti else { 844133211Sharti if (n1->type == NODE_TREE && n2->type == NODE_TREE) { 845133211Sharti if (strcmp(n1->name, n2->name) != 0) 846133211Sharti errx(1, "trees to merge must have " 847133211Sharti "same name '%s' '%s'", n1->name, 848133211Sharti n2->name); 849133211Sharti merge_subs(&n1->u.tree.subs, &n2->u.tree.subs); 850133211Sharti free(n2); 851133211Sharti } else if (n1->type == NODE_ENTRY && 852133211Sharti n2->type == NODE_ENTRY) { 853133211Sharti if (strcmp(n1->name, n2->name) != 0) 854133211Sharti errx(1, "entries to merge must have " 855133211Sharti "same name '%s' '%s'", n1->name, 856133211Sharti n2->name); 857133211Sharti if (n1->u.entry.index != n2->u.entry.index) 858133211Sharti errx(1, "entries to merge must have " 859133211Sharti "same index '%s'", n1->name); 860133211Sharti if (strcmp(n1->u.entry.func, 861133211Sharti n2->u.entry.func) != 0) 862133211Sharti errx(1, "entries to merge must have " 863133211Sharti "same op '%s'", n1->name); 864133211Sharti merge_subs(&n1->u.entry.subs, 865133211Sharti &n2->u.entry.subs); 866133211Sharti free(n2); 867133211Sharti } else 868133211Sharti errx(1, "entities to merge must be both " 869133211Sharti "trees or both entries: %s, %s", 870133211Sharti n1->name, n2->name); 871133211Sharti } 872133211Sharti } 873133211Sharti} 874133211Sharti 875133211Shartistatic void 876133211Shartimerge(struct node *root, struct node *t) 877133211Sharti{ 878133211Sharti 879133211Sharti /* both must be trees */ 880133211Sharti if (root->type != NODE_TREE) 881133211Sharti errx(1, "root is not a tree"); 882133211Sharti if (t->type != NODE_TREE) 883133211Sharti errx(1, "can merge only with tree"); 884133211Sharti if (root->id != t->id) 885133211Sharti errx(1, "trees to merge must have same id"); 886133211Sharti 887133211Sharti merge_subs(&root->u.tree.subs, &t->u.tree.subs); 888133211Sharti} 889133211Sharti 890122394Shartiint 891122394Shartimain(int argc, char *argv[]) 892122394Sharti{ 893122394Sharti int do_extract = 0; 894133211Sharti int do_tree = 0; 895122394Sharti int opt; 896122394Sharti struct node *root; 897122394Sharti char fname[MAXPATHLEN + 1]; 898133211Sharti int tok; 899122394Sharti 900133211Sharti while ((opt = getopt(argc, argv, "help:t")) != EOF) 901122394Sharti switch (opt) { 902122394Sharti 903122394Sharti case 'h': 904122394Sharti fprintf(stderr, "%s", usgtxt); 905122394Sharti exit(0); 906122394Sharti 907122394Sharti case 'e': 908122394Sharti do_extract = 1; 909122394Sharti break; 910122394Sharti 911122394Sharti case 'l': 912122394Sharti localincs = 1; 913122394Sharti break; 914122394Sharti 915122394Sharti case 'p': 916122394Sharti file_prefix = optarg; 917122394Sharti if (strlen(file_prefix) + strlen("tree.c") > 918122394Sharti MAXPATHLEN) 919122394Sharti errx(1, "prefix too long"); 920122394Sharti break; 921133211Sharti 922133211Sharti case 't': 923133211Sharti do_tree = 1; 924133211Sharti break; 925122394Sharti } 926122394Sharti 927133211Sharti if (do_extract && do_tree) 928133211Sharti errx(1, "conflicting options -e and -t"); 929122394Sharti if (!do_extract && argc != optind) 930122394Sharti errx(1, "no arguments allowed"); 931122394Sharti if (do_extract && argc == optind) 932122394Sharti errx(1, "no objects specified"); 933122394Sharti 934122394Sharti root = parse(gettoken()); 935133211Sharti while ((tok = gettoken()) != TOK_EOF) 936133211Sharti merge(root, parse(tok)); 937122394Sharti 938122394Sharti check_tree(root); 939122394Sharti 940122394Sharti if (do_extract) { 941122394Sharti fp = stdout; 942122394Sharti while (optind < argc) { 943122394Sharti if (gen_extract(root, argv[optind])) 944122394Sharti errx(1, "object not found: %s", argv[optind]); 945122394Sharti optind++; 946122394Sharti } 947122394Sharti 948122394Sharti return (0); 949122394Sharti } 950133211Sharti if (do_tree) { 951133211Sharti gen_tree(root, 0); 952133211Sharti return (0); 953133211Sharti } 954122394Sharti sprintf(fname, "%stree.h", file_prefix); 955122394Sharti if ((fp = fopen(fname, "w")) == NULL) 956122394Sharti err(1, "%s: ", fname); 957122394Sharti gen_header(root, PREFIX_LEN, NULL); 958122394Sharti 959122394Sharti fprintf(fp, "#define %sCTREE_SIZE %u\n", file_prefix, tree_size); 960122394Sharti fprintf(fp, "extern const struct snmp_node %sctree[];\n", file_prefix); 961122394Sharti 962122394Sharti fclose(fp); 963122394Sharti 964122394Sharti sprintf(fname, "%stree.c", file_prefix); 965122394Sharti if ((fp = fopen(fname, "w")) == NULL) 966122394Sharti err(1, "%s: ", fname); 967122394Sharti gen_table(root); 968122394Sharti fclose(fp); 969122394Sharti 970122394Sharti return (0); 971122394Sharti} 972