gensnmptree.c revision 128237
1122394Sharti/* 2122394Sharti * Copyright (c) 2001-2003 3122394Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4122394Sharti * All rights reserved. 5122394Sharti * 6122394Sharti * Author: Harti Brandt <harti@freebsd.org> 7122394Sharti * 8122394Sharti * Redistribution of this software and documentation and use in source and 9122394Sharti * binary forms, with or without modification, are permitted provided that 10122394Sharti * the following conditions are met: 11122394Sharti * 12122394Sharti * 1. Redistributions of source code or documentation must retain the above 13122394Sharti * copyright notice, this list of conditions and the following disclaimer. 14122394Sharti * 2. Redistributions in binary form must reproduce the above copyright 15122394Sharti * notice, this list of conditions and the following disclaimer in the 16122394Sharti * documentation and/or other materials provided with the distribution. 17122394Sharti * 3. Neither the name of the Institute nor the names of its contributors 18122394Sharti * may be used to endorse or promote products derived from this software 19122394Sharti * without specific prior written permission. 20122394Sharti * 21122394Sharti * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY FRAUNHOFER FOKUS 22122394Sharti * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 23122394Sharti * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 24122394Sharti * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 25122394Sharti * FRAUNHOFER FOKUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26122394Sharti * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27122394Sharti * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 28122394Sharti * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29122394Sharti * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30122394Sharti * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 31122394Sharti * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32122394Sharti * 33128237Sharti * $Begemot: bsnmp/gensnmptree/gensnmptree.c,v 1.37 2004/04/13 15:18:15 novo Exp $ 34122394Sharti * 35122394Sharti * Generate OID table from table description. 36122394Sharti * 37122394Sharti * Syntax is: 38122394Sharti * --------- 39122394Sharti * tree := head elements ')' 40122394Sharti * 41122394Sharti * entry := head ':' index STRING elements ')' 42122394Sharti * 43122394Sharti * leaf := head TYPE STRING ACCESS ')' 44122394Sharti * 45122394Sharti * column := head TYPE ACCESS ')' 46122394Sharti * 47122394Sharti * head := '(' INT STRING 48122394Sharti * 49122394Sharti * elements := EMPTY | elements element 50122394Sharti * 51122394Sharti * element := tree | leaf 52122394Sharti * 53122394Sharti * index := TYPE | index TYPE 54122394Sharti * 55122394Sharti */ 56122394Sharti#include <sys/types.h> 57122394Sharti#include <sys/param.h> 58122394Sharti#include <stdio.h> 59122394Sharti#include <stdlib.h> 60122394Sharti#include <stdarg.h> 61122394Sharti#include <unistd.h> 62122394Sharti#include <string.h> 63122394Sharti#include <ctype.h> 64122394Sharti#include <err.h> 65122394Sharti#include <sys/queue.h> 66122394Sharti#include "asn1.h" 67122394Sharti#include "snmp.h" 68122394Sharti#include "snmpagent.h" 69122394Sharti 70122394Sharti/* 71122394Sharti * Constant prefix for all OIDs 72122394Sharti */ 73122394Shartistatic const asn_subid_t prefix[] = { 1, 3, 6 }; 74122394Sharti#define PREFIX_LEN (sizeof(prefix) / sizeof(prefix[0])) 75122394Sharti 76122394Shartiu_int tree_size; 77122394Shartistatic const char *file_prefix = ""; 78122394Shartistatic FILE *fp; 79122394Sharti 80122394Sharti/* if true generate local include paths */ 81122394Shartistatic int localincs = 0; 82122394Sharti 83122394Shartistatic const char usgtxt[] = "\ 84122394ShartiGenerate SNMP tables. Copyright (c) 2001-2002 Fraunhofer Institute for\n\ 85122394ShartiOpen Communication Systems (FhG Fokus). All rights reserved.\n\ 86122394Shartiusage: gensnmptree [-hel] [-p prefix] [name]...\n\ 87122394Shartioptions:\n\ 88122394Sharti -h print this info\n\ 89122394Sharti -e extrace the named oids\n\ 90122394Sharti -l generate local include directives\n\ 91122394Sharti -p prefix prepend prefix to file and variable names\n\ 92122394Sharti"; 93122394Sharti 94122394Sharti/* 95122394Sharti * A node in the OID tree 96122394Sharti */ 97122394Shartienum ntype { 98122394Sharti NODE_LEAF = 1, 99122394Sharti NODE_TREE, 100122394Sharti NODE_ENTRY, 101122394Sharti NODE_COLUMN 102122394Sharti}; 103122394Sharti 104122394Shartienum { 105122394Sharti FL_GET = 0x01, 106122394Sharti FL_SET = 0x02, 107122394Sharti}; 108122394Sharti 109122394Shartistruct node; 110122394ShartiTAILQ_HEAD(node_list, node); 111122394Sharti 112122394Shartistruct node { 113122394Sharti enum ntype type; 114122394Sharti asn_subid_t id; /* last element of OID */ 115122394Sharti char *name; /* name of node */ 116122394Sharti TAILQ_ENTRY(node) link; 117122394Sharti u_int lno; /* starting line number */ 118122394Sharti u_int flags; /* allowed operations */ 119122394Sharti 120122394Sharti union { 121122394Sharti struct tree { 122122394Sharti struct node_list subs; 123122394Sharti } tree; 124122394Sharti 125122394Sharti struct entry { 126122394Sharti u_int32_t index; /* index for table entry */ 127122394Sharti char *func; /* function for tables */ 128122394Sharti struct node_list subs; 129122394Sharti } entry; 130122394Sharti 131122394Sharti struct leaf { 132122394Sharti enum snmp_syntax syntax; /* syntax for this leaf */ 133122394Sharti char *func; /* function name */ 134122394Sharti } leaf; 135122394Sharti 136122394Sharti struct column { 137122394Sharti enum snmp_syntax syntax; /* syntax for this column */ 138122394Sharti } column; 139122394Sharti } u; 140122394Sharti}; 141122394Sharti 142122394Shartistruct func { 143122394Sharti const char *name; 144122394Sharti LIST_ENTRY(func) link; 145122394Sharti}; 146122394Sharti 147122394Shartistatic LIST_HEAD(, func) funcs = LIST_HEAD_INITIALIZER(funcs); 148122394Sharti 149122394Sharti/************************************************************ 150122394Sharti * 151122394Sharti * Allocate memory and panic just in the case... 152122394Sharti */ 153122394Shartistatic void * 154122394Shartixalloc(size_t size) 155122394Sharti{ 156122394Sharti void *ptr; 157122394Sharti 158122394Sharti if ((ptr = malloc(size)) == NULL) 159122394Sharti err(1, "allocing %u bytes", size); 160122394Sharti 161122394Sharti return (ptr); 162122394Sharti} 163122394Sharti 164122394Sharti/************************************************************ 165122394Sharti * 166122394Sharti * Parsing input 167122394Sharti */ 168122394Shartienum tok { 169122394Sharti TOK_EOF = 0200, /* end-of-file seen */ 170122394Sharti TOK_NUM, /* number */ 171122394Sharti TOK_STR, /* string */ 172122394Sharti TOK_ACCESS, /* access operator */ 173122394Sharti TOK_TYPE, /* type operator */ 174122394Sharti}; 175122394Sharti 176122394Shartistatic const struct { 177122394Sharti const char *str; 178122394Sharti enum tok tok; 179122394Sharti u_int val; 180122394Sharti} keywords[] = { 181122394Sharti { "GET", TOK_ACCESS, FL_GET }, 182122394Sharti { "SET", TOK_ACCESS, FL_SET }, 183122394Sharti { "NULL", TOK_TYPE, SNMP_SYNTAX_NULL }, 184122394Sharti { "INTEGER", TOK_TYPE, SNMP_SYNTAX_INTEGER }, 185122394Sharti { "INTEGER32", TOK_TYPE, SNMP_SYNTAX_INTEGER }, 186122394Sharti { "UNSIGNED32", TOK_TYPE, SNMP_SYNTAX_GAUGE }, 187122394Sharti { "OCTETSTRING", TOK_TYPE, SNMP_SYNTAX_OCTETSTRING }, 188122394Sharti { "IPADDRESS", TOK_TYPE, SNMP_SYNTAX_IPADDRESS }, 189122394Sharti { "OID", TOK_TYPE, SNMP_SYNTAX_OID }, 190122394Sharti { "TIMETICKS", TOK_TYPE, SNMP_SYNTAX_TIMETICKS }, 191122394Sharti { "COUNTER", TOK_TYPE, SNMP_SYNTAX_COUNTER }, 192122394Sharti { "GAUGE", TOK_TYPE, SNMP_SYNTAX_GAUGE }, 193122394Sharti { "COUNTER64", TOK_TYPE, SNMP_SYNTAX_COUNTER64 }, 194122394Sharti { NULL, 0, 0 } 195122394Sharti}; 196122394Sharti 197122394Sharti/* arbitrary upper limit on node names and function names */ 198122394Sharti#define MAXSTR 1000 199122394Shartichar str[MAXSTR]; 200122394Shartiu_long val; /* integer values */ 201122394Shartiu_int lno = 1; /* current line number */ 202122394Sharti 203122394Shartistatic void report(const char *, ...) __dead2 __printflike(1, 2); 204122394Shartistatic void report_node(const struct node *, const char *, ...) 205122394Sharti __dead2 __printflike(2, 3); 206122394Sharti 207122394Sharti/* 208122394Sharti * Report an error and exit. 209122394Sharti */ 210122394Shartistatic void 211122394Shartireport(const char *fmt, ...) 212122394Sharti{ 213122394Sharti va_list ap; 214122394Sharti int c; 215122394Sharti 216122394Sharti va_start(ap, fmt); 217122394Sharti fprintf(stderr, "line %u: ", lno); 218122394Sharti vfprintf(stderr, fmt, ap); 219122394Sharti fprintf(stderr, "\n"); 220122394Sharti fprintf(stderr, "context: \""); 221122394Sharti while ((c = getchar()) != EOF && c != '\n') 222122394Sharti fprintf(stderr, "%c", c); 223122394Sharti fprintf(stderr, "\n"); 224122394Sharti va_end(ap); 225122394Sharti exit(1); 226122394Sharti} 227122394Shartistatic void 228122394Shartireport_node(const struct node *np, const char *fmt, ...) 229122394Sharti{ 230122394Sharti va_list ap; 231122394Sharti 232122394Sharti va_start(ap, fmt); 233122394Sharti fprintf(stderr, "line %u, node %s: ", np->lno, np->name); 234122394Sharti vfprintf(stderr, fmt, ap); 235122394Sharti fprintf(stderr, "\n"); 236122394Sharti va_end(ap); 237122394Sharti exit(1); 238122394Sharti} 239122394Sharti 240122394Sharti/* 241122394Sharti * Return a fresh copy of the string constituting the current token. 242122394Sharti */ 243122394Shartistatic char * 244122394Shartisavetok(void) 245122394Sharti{ 246122394Sharti return (strcpy(xalloc(strlen(str)+1), str)); 247122394Sharti} 248122394Sharti 249122394Sharti/* 250122394Sharti * Get the next token from input. 251122394Sharti */ 252122394Shartistatic int 253122394Shartigettoken(void) 254122394Sharti{ 255122394Sharti int c; 256122394Sharti 257122394Sharti again: 258122394Sharti /* 259122394Sharti * Skip any whitespace before the next token 260122394Sharti */ 261122394Sharti while ((c = getchar()) != EOF) { 262122394Sharti if (c == '\n') 263122394Sharti lno++; 264122394Sharti if (!isspace(c)) 265122394Sharti break; 266122394Sharti } 267122394Sharti if (c == EOF) 268122394Sharti return (TOK_EOF); 269122394Sharti if (!isascii(c)) 270122394Sharti report("unexpected character %#2x", (u_int)c); 271122394Sharti 272122394Sharti /* 273122394Sharti * Skip comments 274122394Sharti */ 275122394Sharti if (c == '#') { 276122394Sharti while ((c = getchar()) != EOF) { 277122394Sharti if (c == '\n') { 278122394Sharti lno++; 279122394Sharti goto again; 280122394Sharti } 281122394Sharti } 282122394Sharti report("unexpected EOF in comment"); 283122394Sharti } 284122394Sharti 285122394Sharti /* 286122394Sharti * Single character tokens 287122394Sharti */ 288122394Sharti if (c == ')' || c == '(' || c == ':') 289122394Sharti return (c); 290122394Sharti 291122394Sharti /* 292122394Sharti * Sort out numbers 293122394Sharti */ 294122394Sharti if (isdigit(c)) { 295122394Sharti ungetc(c, stdin); 296122394Sharti scanf("%lu", &val); 297122394Sharti return (TOK_NUM); 298122394Sharti } 299122394Sharti 300122394Sharti /* 301122394Sharti * So that has to be a string. 302122394Sharti */ 303122394Sharti if (isalpha(c) || c == '_') { 304122394Sharti size_t n = 0; 305122394Sharti str[n++] = c; 306122394Sharti while ((c = getchar()) != EOF) { 307122394Sharti if (!isalnum(c) && c != '_') { 308122394Sharti ungetc(c, stdin); 309122394Sharti break; 310122394Sharti } 311122394Sharti if (n == sizeof(str) - 1) { 312122394Sharti str[n++] = '\0'; 313122394Sharti report("string too long '%s...'", str); 314122394Sharti } 315122394Sharti str[n++] = c; 316122394Sharti } 317122394Sharti str[n++] = '\0'; 318122394Sharti 319122394Sharti /* 320122394Sharti * Keywords 321122394Sharti */ 322122394Sharti for (c = 0; keywords[c].str != NULL; c++) 323122394Sharti if (strcmp(keywords[c].str, str) == 0) { 324122394Sharti val = keywords[c].val; 325122394Sharti return (keywords[c].tok); 326122394Sharti } 327122394Sharti 328122394Sharti return (TOK_STR); 329122394Sharti } 330122394Sharti if (isprint(c)) 331122394Sharti errx(1, "%u: unexpected character '%c'", lno, c); 332122394Sharti else 333122394Sharti errx(1, "%u: unexpected character 0x%02x", lno, (u_int)c); 334122394Sharti} 335122394Sharti 336122394Sharti/* 337122394Sharti * Parse the next node (complete with all subnodes) 338122394Sharti */ 339122394Shartistatic struct node * 340122394Shartiparse(enum tok tok) 341122394Sharti{ 342122394Sharti struct node *node; 343122394Sharti struct node *sub; 344122394Sharti u_int index_count; 345122394Sharti 346122394Sharti node = xalloc(sizeof(struct node)); 347122394Sharti node->lno = lno; 348122394Sharti 349122394Sharti if (tok != '(') 350122394Sharti report("'(' expected at begin of node"); 351122394Sharti if (gettoken() != TOK_NUM) 352122394Sharti report("node id expected after opening '('"); 353122394Sharti if (val > ASN_MAXID) 354122394Sharti report("subid too large '%lu'", val); 355122394Sharti node->id = (asn_subid_t)val; 356122394Sharti if (gettoken() != TOK_STR) 357122394Sharti report("node name expected after '(' ID"); 358122394Sharti node->name = savetok(); 359122394Sharti 360122394Sharti if ((tok = gettoken()) == TOK_TYPE) { 361122394Sharti /* LEAF or COLUM */ 362122394Sharti u_int syntax = val; 363122394Sharti 364122394Sharti if ((tok = gettoken()) == TOK_STR) { 365122394Sharti /* LEAF */ 366122394Sharti node->type = NODE_LEAF; 367122394Sharti node->u.leaf.func = savetok(); 368122394Sharti node->u.leaf.syntax = syntax; 369122394Sharti tok = gettoken(); 370122394Sharti } else { 371122394Sharti /* COLUMN */ 372122394Sharti node->type = NODE_COLUMN; 373122394Sharti node->u.column.syntax = syntax; 374122394Sharti } 375122394Sharti 376122394Sharti while (tok != ')') { 377122394Sharti if (tok != TOK_ACCESS) 378122394Sharti report("access keyword or ')' expected"); 379122394Sharti node->flags |= (u_int)val; 380122394Sharti tok = gettoken(); 381122394Sharti } 382122394Sharti 383122394Sharti } else if (tok == ':') { 384122394Sharti /* ENTRY */ 385122394Sharti node->type = NODE_ENTRY; 386122394Sharti TAILQ_INIT(&node->u.entry.subs); 387122394Sharti 388122394Sharti index_count = 0; 389122394Sharti node->u.entry.index = 0; 390122394Sharti while ((tok = gettoken()) == TOK_TYPE) { 391122394Sharti if (index_count++ == SNMP_INDEXES_MAX) 392122394Sharti report("too many table indexes"); 393122394Sharti node->u.entry.index |= 394122394Sharti val << (SNMP_INDEX_SHIFT * index_count); 395122394Sharti } 396122394Sharti node->u.entry.index |= index_count; 397122394Sharti if (index_count == 0) 398122394Sharti report("need at least one index"); 399122394Sharti 400122394Sharti if (tok != TOK_STR) 401122394Sharti report("function name expected"); 402122394Sharti 403122394Sharti node->u.entry.func = savetok(); 404122394Sharti 405122394Sharti tok = gettoken(); 406122394Sharti 407122394Sharti while (tok != ')') { 408122394Sharti sub = parse(tok); 409122394Sharti TAILQ_INSERT_TAIL(&node->u.entry.subs, sub, link); 410122394Sharti tok = gettoken(); 411122394Sharti } 412122394Sharti 413122394Sharti } else { 414122394Sharti /* subtree */ 415122394Sharti node->type = NODE_TREE; 416122394Sharti TAILQ_INIT(&node->u.tree.subs); 417122394Sharti 418122394Sharti while (tok != ')') { 419122394Sharti sub = parse(tok); 420122394Sharti TAILQ_INSERT_TAIL(&node->u.tree.subs, sub, link); 421122394Sharti tok = gettoken(); 422122394Sharti } 423122394Sharti } 424122394Sharti return (node); 425122394Sharti} 426122394Sharti 427122394Sharti/* 428122394Sharti * Generate the C-code table part for one node. 429122394Sharti */ 430122394Shartistatic void 431122394Shartigen_node(struct node *np, struct asn_oid *oid, u_int idx, const char *func) 432122394Sharti{ 433122394Sharti u_int n; 434122394Sharti struct node *sub; 435122394Sharti u_int syntax; 436122394Sharti 437122394Sharti if (oid->len == ASN_MAXOIDLEN) 438122394Sharti report_node(np, "OID too long"); 439122394Sharti oid->subs[oid->len++] = np->id; 440122394Sharti 441122394Sharti if (np->type == NODE_TREE) { 442122394Sharti TAILQ_FOREACH(sub, &np->u.tree.subs, link) 443122394Sharti gen_node(sub, oid, 0, NULL); 444122394Sharti oid->len--; 445122394Sharti return; 446122394Sharti } 447122394Sharti if (np->type == NODE_ENTRY) { 448122394Sharti TAILQ_FOREACH(sub, &np->u.entry.subs, link) 449122394Sharti gen_node(sub, oid, np->u.entry.index, np->u.entry.func); 450122394Sharti oid->len--; 451122394Sharti return; 452122394Sharti } 453122394Sharti 454122394Sharti /* leaf or column */ 455122394Sharti if ((np->flags & (FL_GET|FL_SET)) == 0) { 456122394Sharti oid->len--; 457122394Sharti return; 458122394Sharti } 459122394Sharti 460122394Sharti fprintf(fp, " {{ %u, {", oid->len); 461122394Sharti for (n = 0; n < oid->len; n++) 462122394Sharti fprintf(fp, " %u,", oid->subs[n]); 463122394Sharti fprintf(fp, " }}, \"%s\", ", np->name); 464122394Sharti 465122394Sharti if (np->type == NODE_COLUMN) { 466122394Sharti syntax = np->u.column.syntax; 467122394Sharti fprintf(fp, "SNMP_NODE_COLUMN, "); 468122394Sharti } else { 469122394Sharti syntax = np->u.leaf.syntax; 470122394Sharti fprintf(fp, "SNMP_NODE_LEAF, "); 471122394Sharti } 472122394Sharti 473122394Sharti switch (syntax) { 474122394Sharti 475122394Sharti case SNMP_SYNTAX_NULL: 476122394Sharti fprintf(fp, "SNMP_SYNTAX_NULL, "); 477122394Sharti break; 478122394Sharti 479122394Sharti case SNMP_SYNTAX_INTEGER: 480122394Sharti fprintf(fp, "SNMP_SYNTAX_INTEGER, "); 481122394Sharti break; 482122394Sharti 483122394Sharti case SNMP_SYNTAX_OCTETSTRING: 484122394Sharti fprintf(fp, "SNMP_SYNTAX_OCTETSTRING, "); 485122394Sharti break; 486122394Sharti 487122394Sharti case SNMP_SYNTAX_IPADDRESS: 488122394Sharti fprintf(fp, "SNMP_SYNTAX_IPADDRESS, "); 489122394Sharti break; 490122394Sharti 491122394Sharti case SNMP_SYNTAX_OID: 492122394Sharti fprintf(fp, "SNMP_SYNTAX_OID, "); 493122394Sharti break; 494122394Sharti 495122394Sharti case SNMP_SYNTAX_TIMETICKS: 496122394Sharti fprintf(fp, "SNMP_SYNTAX_TIMETICKS, "); 497122394Sharti break; 498122394Sharti 499122394Sharti case SNMP_SYNTAX_COUNTER: 500122394Sharti fprintf(fp, "SNMP_SYNTAX_COUNTER, "); 501122394Sharti break; 502122394Sharti 503122394Sharti case SNMP_SYNTAX_GAUGE: 504122394Sharti fprintf(fp, "SNMP_SYNTAX_GAUGE, "); 505122394Sharti break; 506122394Sharti 507122394Sharti case SNMP_SYNTAX_COUNTER64: 508122394Sharti fprintf(fp, "SNMP_SYNTAX_COUNTER64, "); 509122394Sharti break; 510122394Sharti 511122394Sharti case SNMP_SYNTAX_NOSUCHOBJECT: 512122394Sharti case SNMP_SYNTAX_NOSUCHINSTANCE: 513122394Sharti case SNMP_SYNTAX_ENDOFMIBVIEW: 514122394Sharti abort(); 515122394Sharti } 516122394Sharti 517122394Sharti if (np->type == NODE_COLUMN) 518122394Sharti fprintf(fp, "%s, ", func); 519122394Sharti else 520122394Sharti fprintf(fp, "%s, ", np->u.leaf.func); 521122394Sharti 522122394Sharti fprintf(fp, "0"); 523122394Sharti if (np->flags & FL_SET) 524122394Sharti fprintf(fp, "|SNMP_NODE_CANSET"); 525128237Sharti fprintf(fp, ", %#x, NULL, NULL },\n", idx); 526122394Sharti oid->len--; 527122394Sharti return; 528122394Sharti} 529122394Sharti 530122394Sharti/* 531122394Sharti * Generate the header file with the function declarations. 532122394Sharti */ 533122394Shartistatic void 534122394Shartigen_header(struct node *np, u_int oidlen, const char *func) 535122394Sharti{ 536122394Sharti char f[MAXSTR + 4]; 537122394Sharti struct node *sub; 538122394Sharti struct func *ptr; 539122394Sharti 540122394Sharti oidlen++; 541122394Sharti if (np->type == NODE_TREE) { 542122394Sharti TAILQ_FOREACH(sub, &np->u.tree.subs, link) 543122394Sharti gen_header(sub, oidlen, NULL); 544122394Sharti return; 545122394Sharti } 546122394Sharti if (np->type == NODE_ENTRY) { 547122394Sharti TAILQ_FOREACH(sub, &np->u.entry.subs, link) 548122394Sharti gen_header(sub, oidlen, np->u.entry.func); 549122394Sharti return; 550122394Sharti } 551122394Sharti 552122394Sharti if((np->flags & (FL_GET|FL_SET)) == 0) 553122394Sharti return; 554122394Sharti 555122394Sharti if (np->type == NODE_COLUMN) 556122394Sharti sprintf(f, "%s", func); 557122394Sharti else 558122394Sharti sprintf(f, "%s", np->u.leaf.func); 559122394Sharti 560122394Sharti LIST_FOREACH(ptr, &funcs, link) 561122394Sharti if (strcmp(ptr->name, f) == 0) 562122394Sharti break; 563122394Sharti 564122394Sharti if (ptr == NULL) { 565122394Sharti ptr = xalloc(sizeof(*ptr)); 566122394Sharti ptr->name = strcpy(xalloc(strlen(f)+1), f); 567122394Sharti LIST_INSERT_HEAD(&funcs, ptr, link); 568122394Sharti 569122394Sharti fprintf(fp, "int %s(struct snmp_context *, " 570122394Sharti "struct snmp_value *, u_int, u_int, " 571122394Sharti "enum snmp_op);\n", f); 572122394Sharti } 573122394Sharti 574122394Sharti fprintf(fp, "# define LEAF_%s %u\n", np->name, np->id); 575122394Sharti} 576122394Sharti 577122394Sharti/* 578122394Sharti * Generate the OID table. 579122394Sharti */ 580122394Shartistatic void 581122394Shartigen_table(struct node *node) 582122394Sharti{ 583122394Sharti struct asn_oid oid; 584122394Sharti 585122394Sharti fprintf(fp, "#include <sys/types.h>\n"); 586122394Sharti fprintf(fp, "#include <stdio.h>\n"); 587122394Sharti if (localincs) { 588122394Sharti fprintf(fp, "#include \"asn1.h\"\n"); 589122394Sharti fprintf(fp, "#include \"snmp.h\"\n"); 590122394Sharti fprintf(fp, "#include \"snmpagent.h\"\n"); 591122394Sharti } else { 592122394Sharti fprintf(fp, "#include <bsnmp/asn1.h>\n"); 593122394Sharti fprintf(fp, "#include <bsnmp/snmp.h>\n"); 594122394Sharti fprintf(fp, "#include <bsnmp/snmpagent.h>\n"); 595122394Sharti } 596122394Sharti fprintf(fp, "#include \"%stree.h\"\n", file_prefix); 597122394Sharti fprintf(fp, "\n"); 598122394Sharti 599122394Sharti fprintf(fp, "const struct snmp_node %sctree[] = {\n", file_prefix); 600122394Sharti 601122394Sharti oid.len = PREFIX_LEN; 602122394Sharti memcpy(oid.subs, prefix, sizeof(prefix)); 603122394Sharti gen_node(node, &oid, 0, NULL); 604122394Sharti 605122394Sharti fprintf(fp, "};\n\n"); 606122394Sharti} 607122394Sharti 608122394Shartistatic int 609122394Shartiextract(const struct node *np, struct asn_oid *oid, const char *obj) 610122394Sharti{ 611122394Sharti struct node *sub; 612122394Sharti u_long n; 613122394Sharti 614122394Sharti if (oid->len == ASN_MAXOIDLEN) 615122394Sharti report_node(np, "OID too long"); 616122394Sharti oid->subs[oid->len++] = np->id; 617122394Sharti 618122394Sharti if (strcmp(obj, np->name) == 0) { 619122394Sharti fprintf(fp, "#define OID_%s\t%u\n", np->name, np->id); 620122394Sharti fprintf(fp, "#define OIDLEN_%s\t%u\n", np->name, oid->len); 621122394Sharti fprintf(fp, "#define OIDX_%s\t{ %u, {", np->name, oid->len); 622122394Sharti for (n = 0; n < oid->len; n++) 623122394Sharti fprintf(fp, " %u,", oid->subs[n]); 624122394Sharti fprintf(fp, " } }\n"); 625122394Sharti return (0); 626122394Sharti } 627122394Sharti 628122394Sharti if (np->type == NODE_TREE) { 629122394Sharti TAILQ_FOREACH(sub, &np->u.tree.subs, link) 630122394Sharti if (!extract(sub, oid, obj)) 631122394Sharti return (0); 632122394Sharti } else if (np->type == NODE_ENTRY) { 633122394Sharti TAILQ_FOREACH(sub, &np->u.entry.subs, link) 634122394Sharti if (!extract(sub, oid, obj)) 635122394Sharti return (0); 636122394Sharti } 637122394Sharti oid->len--; 638122394Sharti return (1); 639122394Sharti} 640122394Sharti 641122394Shartistatic int 642122394Shartigen_extract(const struct node *root, const char *object) 643122394Sharti{ 644122394Sharti struct asn_oid oid; 645122394Sharti 646122394Sharti oid.len = PREFIX_LEN; 647122394Sharti memcpy(oid.subs, prefix, sizeof(prefix)); 648122394Sharti return (extract(root, &oid, object)); 649122394Sharti} 650122394Sharti 651122394Sharti 652122394Shartistatic void 653122394Sharticheck_sub_order(const struct node *np, const struct node_list *subs) 654122394Sharti{ 655122394Sharti int first; 656122394Sharti const struct node *sub; 657122394Sharti asn_subid_t maxid = 0; 658122394Sharti 659122394Sharti /* ensure, that subids are ordered */ 660122394Sharti first = 1; 661122394Sharti TAILQ_FOREACH(sub, subs, link) { 662122394Sharti if (!first && sub->id <= maxid) 663122394Sharti report_node(np, "subids not ordered at %s", sub->name); 664122394Sharti maxid = sub->id; 665122394Sharti first = 0; 666122394Sharti } 667122394Sharti} 668122394Sharti 669122394Sharti/* 670122394Sharti * Do some sanity checks on the tree definition and do some computations. 671122394Sharti */ 672122394Shartistatic void 673122394Sharticheck_tree(struct node *np) 674122394Sharti{ 675122394Sharti struct node *sub; 676122394Sharti 677122394Sharti if (np->type == NODE_LEAF || np->type == NODE_COLUMN) { 678122394Sharti if ((np->flags & (FL_GET|FL_SET)) != 0) 679122394Sharti tree_size++; 680122394Sharti return; 681122394Sharti } 682122394Sharti 683122394Sharti if (np->type == NODE_ENTRY) { 684122394Sharti check_sub_order(np, &np->u.entry.subs); 685122394Sharti 686122394Sharti /* ensure all subnodes are columns */ 687122394Sharti TAILQ_FOREACH(sub, &np->u.entry.subs, link) { 688122394Sharti if (sub->type != NODE_COLUMN) 689122394Sharti report_node(np, "entry subnode '%s' is not " 690122394Sharti "a column", sub->name); 691122394Sharti check_tree(sub); 692122394Sharti } 693122394Sharti } else { 694122394Sharti check_sub_order(np, &np->u.tree.subs); 695122394Sharti 696122394Sharti TAILQ_FOREACH(sub, &np->u.tree.subs, link) 697122394Sharti check_tree(sub); 698122394Sharti } 699122394Sharti} 700122394Sharti 701122394Shartiint 702122394Shartimain(int argc, char *argv[]) 703122394Sharti{ 704122394Sharti int do_extract = 0; 705122394Sharti int opt; 706122394Sharti struct node *root; 707122394Sharti char fname[MAXPATHLEN + 1]; 708122394Sharti 709122394Sharti while ((opt = getopt(argc, argv, "help:")) != EOF) 710122394Sharti switch (opt) { 711122394Sharti 712122394Sharti case 'h': 713122394Sharti fprintf(stderr, "%s", usgtxt); 714122394Sharti exit(0); 715122394Sharti 716122394Sharti case 'e': 717122394Sharti do_extract = 1; 718122394Sharti break; 719122394Sharti 720122394Sharti case 'l': 721122394Sharti localincs = 1; 722122394Sharti break; 723122394Sharti 724122394Sharti case 'p': 725122394Sharti file_prefix = optarg; 726122394Sharti if (strlen(file_prefix) + strlen("tree.c") > 727122394Sharti MAXPATHLEN) 728122394Sharti errx(1, "prefix too long"); 729122394Sharti break; 730122394Sharti } 731122394Sharti 732122394Sharti if (!do_extract && argc != optind) 733122394Sharti errx(1, "no arguments allowed"); 734122394Sharti if (do_extract && argc == optind) 735122394Sharti errx(1, "no objects specified"); 736122394Sharti 737122394Sharti root = parse(gettoken()); 738122394Sharti if (gettoken() != TOK_EOF) 739122394Sharti report("junk after closing ')'"); 740122394Sharti 741122394Sharti check_tree(root); 742122394Sharti 743122394Sharti if (do_extract) { 744122394Sharti fp = stdout; 745122394Sharti while (optind < argc) { 746122394Sharti if (gen_extract(root, argv[optind])) 747122394Sharti errx(1, "object not found: %s", argv[optind]); 748122394Sharti optind++; 749122394Sharti } 750122394Sharti 751122394Sharti return (0); 752122394Sharti } 753122394Sharti sprintf(fname, "%stree.h", file_prefix); 754122394Sharti if ((fp = fopen(fname, "w")) == NULL) 755122394Sharti err(1, "%s: ", fname); 756122394Sharti gen_header(root, PREFIX_LEN, NULL); 757122394Sharti 758122394Sharti fprintf(fp, "#define %sCTREE_SIZE %u\n", file_prefix, tree_size); 759122394Sharti fprintf(fp, "extern const struct snmp_node %sctree[];\n", file_prefix); 760122394Sharti 761122394Sharti fclose(fp); 762122394Sharti 763122394Sharti sprintf(fname, "%stree.c", file_prefix); 764122394Sharti if ((fp = fopen(fname, "w")) == NULL) 765122394Sharti err(1, "%s: ", fname); 766122394Sharti gen_table(root); 767122394Sharti fclose(fp); 768122394Sharti 769122394Sharti return (0); 770122394Sharti} 771