Path: blob/main/contrib/bsnmp/gensnmpdef/gensnmpdef.c
39478 views
/*1* Copyright (C) 2004-20062* Hartmut Brandt.3* All rights reserved.4*5* Author: Harti Brandt <[email protected]>6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions9* are met:10* 1. Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer.12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND17* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE18* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE19* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE20* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL21* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS22* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)23* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT24* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY25* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF26* SUCH DAMAGE.27*28* $Begemot: gensnmpdef.c 383 2006-05-30 07:40:49Z brandt_h $29*/30#include <sys/queue.h>3132#include <stdio.h>33#include <stdlib.h>34#include <string.h>35#include <unistd.h>36#include <errno.h>37#include <err.h>38#include <assert.h>39#include <smi.h>4041static const char usgtxt[] =42"Usage: gensnmpdef [-hEe] [-c <cut>] MIB [MIB ...]\n"43"Options:\n"44" -c specify the number of initial sub-oids to cut from the oids\n"45" -E extract named enum types. Print a typedef for all enums defined\n"46" in syntax clauses of normal objects. Suppress normal output.\n"47" -e extract unnamed enum types. Print a typedef for all enums defined\n"48" as textual conventions. Suppress normal output.\n"49" -h print this help\n"50"MIBs are searched according to the libsmi(3) search rules and can\n"51"be specified either by path or module name\n";5253static SmiNode *last_node;54static u_int cut = 3;5556struct tdef {57char *name;58SLIST_ENTRY(tdef) link;59};6061static SLIST_HEAD(, tdef) tdefs = SLIST_HEAD_INITIALIZER(tdefs);62static int do_typedef = 0;6364static void print_node(SmiNode *n, u_int level);6566static void67save_node(SmiNode *n)68{69if (n != NULL)70last_node = n;71}7273static void74pindent(u_int level)75{76if (level >= cut)77printf("%*s", (level - cut) * 2, "");78}7980static void81print_name(SmiNode *n)82{83char *p;8485for (p = n->name; *p != '\0'; p++) {86if (*p == '-')87printf("_");88else89printf("%c", *p);90}91}9293static u_int94close_node(u_int n, u_int level)95{96while (n--) {97pindent(level);98level--;99if (level >= cut)100printf(")\n");101}102return (level);103}104105static u_int106open_node(const SmiNode *n, u_int level, SmiNode **last)107{108SmiNode *n1;109u_int i;110111if (*last != NULL) {112for (i = 0; i < (*last)->oidlen - 1; i++) {113if (i >= n->oidlen) {114level = close_node((*last)->oidlen -115n->oidlen, level);116break;117}118if ((*last)->oid[i] != n->oid[i])119break;120}121if (i < (*last)->oidlen - 1)122level = close_node((*last)->oidlen - 1 - i,123level - 1) + 1;124}125126while (level < n->oidlen - 1) {127if (level >= cut) {128n1 = smiGetNodeByOID(level + 1, n->oid);129if (n1 == NULL)130continue;131pindent(level);132printf("(%u", n->oid[level]);133printf(" ");134print_name(n1);135printf("\n");136}137level++;138}139return (level);140}141142static const char *const type_names[] = {143[SMI_BASETYPE_UNKNOWN] = "UNKNOWN_TYPE",144[SMI_BASETYPE_INTEGER32] = "INTEGER",145[SMI_BASETYPE_OCTETSTRING] = "OCTETSTRING",146[SMI_BASETYPE_OBJECTIDENTIFIER] = "OID",147[SMI_BASETYPE_UNSIGNED32] = "UNSIGNED32",148[SMI_BASETYPE_INTEGER64] = "INTEGER64",149[SMI_BASETYPE_UNSIGNED64] = "UNSIGNED64",150[SMI_BASETYPE_FLOAT32] = "FLOAT32",151[SMI_BASETYPE_FLOAT64] = "FLOAT64",152[SMI_BASETYPE_FLOAT128] = "FLOAT128",153[SMI_BASETYPE_ENUM] = "ENUM",154[SMI_BASETYPE_BITS] = "BITS",155};156157static const char *const type_map[] = {158"Gauge32", "GAUGE",159"Gauge", "GAUGE",160"TimeTicks", "TIMETICKS",161"Counter32", "COUNTER",162"Counter", "COUNTER",163"Counter64", "COUNTER64",164"Integer32", "INTEGER32",165"IpAddress", "IPADDRESS",166NULL167};168169static void170print_enum(SmiType *t)171{172SmiNamedNumber *nnum;173174printf(" (");175for (nnum = smiGetFirstNamedNumber(t); nnum != NULL;176nnum = smiGetNextNamedNumber(nnum))177printf(" %ld %s", nnum->value.value.integer32, nnum->name);178printf(" )");179}180181static void182print_type(SmiNode *n)183{184SmiType *type;185u_int m;186187type = smiGetNodeType(n);188assert(type != NULL);189190if (type->name != NULL) {191for (m = 0; type_map[m] != NULL; m += 2)192if (strcmp(type_map[m], type->name) == 0) {193printf("%s", type_map[m + 1]);194return;195}196}197printf("%s", type_names[type->basetype]);198199if (type->basetype == SMI_BASETYPE_ENUM ||200type->basetype == SMI_BASETYPE_BITS)201print_enum(type);202203else if (type->basetype == SMI_BASETYPE_OCTETSTRING &&204type->name != NULL)205printf(" | %s", type->name);206}207208static void209print_access(SmiAccess a)210{211if (a == SMI_ACCESS_READ_ONLY)212printf(" GET");213else if (a == SMI_ACCESS_READ_WRITE)214printf(" GET SET");215}216217static void218print_scalar(SmiNode *n, u_int level)219{220SmiNode *p;221222assert (n->nodekind == SMI_NODEKIND_SCALAR);223224save_node(n);225226pindent(level);227printf("(%u ", n->oid[level]);228print_name(n);229printf(" ");230print_type(n);231232/* generate the operation from the parent node name */233p = smiGetParentNode(n);234printf(" op_%s", p->name);235236print_access(n->access);237238printf(")\n");239}240241static void242print_notification(SmiNode *n, u_int level)243{244245assert (n->nodekind == SMI_NODEKIND_NOTIFICATION);246247save_node(n);248249pindent(level);250printf("(%u ", n->oid[level]);251print_name(n);252printf(" OID");253254printf(" op_%s)\n", n->name);255}256257static void258print_col(SmiNode *n, u_int level)259{260assert (n->nodekind == SMI_NODEKIND_COLUMN);261262save_node(n);263264pindent(level);265printf("(%u ", n->oid[level]);266print_name(n);267printf(" ");268print_type(n);269print_access(n->access);270printf(")\n");271}272273static void274print_index(SmiNode *row)275{276SmiElement *e;277278e = smiGetFirstElement(row);279while (e != NULL) {280printf(" ");281print_type(smiGetElementNode(e));282e = smiGetNextElement(e);283}284}285286static void287print_table(SmiNode *n, u_int level)288{289SmiNode *row, *col, *rel;290291assert (n->nodekind == SMI_NODEKIND_TABLE);292293save_node(n);294295pindent(level);296printf("(%u ", n->oid[level]);297print_name(n);298printf("\n");299300row = smiGetFirstChildNode(n);301if (row->nodekind != SMI_NODEKIND_ROW)302errx(1, "%s: kind %u, not row", __func__, row->nodekind);303304save_node(n);305306pindent(level + 1);307printf("(%u ", row->oid[level + 1]);308print_name(row);309printf(" :");310311/* index */312rel = smiGetRelatedNode(row);313switch (row->indexkind) {314315case SMI_INDEX_INDEX:316print_index(row);317break;318319case SMI_INDEX_AUGMENT:320if (rel == NULL)321errx(1, "%s: cannot find augemented table", row->name);322print_index(rel);323break;324325default:326errx(1, "%s: cannot handle index kind %u", row->name,327row->indexkind);328}329330printf(" op_%s", n->name);331printf("\n");332333col = smiGetFirstChildNode(row);334while (col != NULL) {335print_col(col, level + 2);336col = smiGetNextChildNode(col);337}338pindent(level + 1);339printf(")\n");340341pindent(level);342printf(")\n");343}344345static void346print_it(SmiNode *n, u_int level)347{348switch (n->nodekind) {349350case SMI_NODEKIND_NODE:351print_node(n, level);352break;353354case SMI_NODEKIND_SCALAR:355print_scalar(n, level);356break;357358case SMI_NODEKIND_TABLE:359print_table(n, level);360break;361362case SMI_NODEKIND_COMPLIANCE:363case SMI_NODEKIND_GROUP:364save_node(n);365break;366367case SMI_NODEKIND_NOTIFICATION:368print_notification(n, level);369break;370371default:372errx(1, "cannot handle %u nodes", n->nodekind);373}374}375376static void377print_node(SmiNode *n, u_int level)378{379assert (n->nodekind == SMI_NODEKIND_NODE);380381save_node(n);382383pindent(level);384printf("(%u ", n->oid[level]);385print_name(n);386printf("\n");387388n = smiGetFirstChildNode(n);389while (n != NULL) {390print_it(n, level + 1);391n = smiGetNextChildNode(n);392}393pindent(level);394printf(")\n");395}396397static void398save_typdef(char *name)399{400struct tdef *t;401402t = calloc(1, sizeof(struct tdef));403if (t == NULL)404err(1, NULL);405406t->name = name;407SLIST_INSERT_HEAD(&tdefs, t, link);408}409410static void411tdefs_cleanup(void)412{413struct tdef *t;414415while ((t = SLIST_FIRST(&tdefs)) != NULL) {416SLIST_REMOVE_HEAD(&tdefs, link);417free(t);418}419}420421static void422print_enum_typedef(SmiType *t)423{424SmiNamedNumber *nnum;425426for (nnum = smiGetFirstNamedNumber(t); nnum != NULL;427nnum = smiGetNextNamedNumber(nnum)) {428printf("\t%ld %s\n" , nnum->value.value.integer32, nnum->name);429}430}431432static void433print_stype(SmiNode *n)434{435SmiType *type;436struct tdef *t = NULL;437438type = smiGetNodeType(n);439assert(type != NULL);440441if (type->basetype == SMI_BASETYPE_ENUM) {442if (do_typedef == 'e' && type->name != NULL) {443SLIST_FOREACH(t, &tdefs, link) {444if (strcmp(t->name, type->name) == 0)445return;446}447save_typdef(type->name);448printf("typedef %s ENUM (\n", type->name);449} else if (do_typedef == 'E' && type->name == NULL)450printf("typedef %sType ENUM (\n", n->name);451else452return;453454print_enum_typedef(type);455printf(")\n\n");456457} else if (type->basetype == SMI_BASETYPE_BITS) {458if (do_typedef == 'e' && type->name != NULL) {459SLIST_FOREACH(t, &tdefs, link) {460if (strcmp(t->name, type->name) == 0)461return;462}463save_typdef(type->name);464printf("typedef %s BITS (\n", type->name);465} else if (do_typedef == 'E' && type->name == NULL)466printf("typedef %sType BITS (\n", n->name);467else468return;469470print_enum_typedef(type);471printf(")\n\n");472}473}474475static void476print_typdefs(SmiNode *n)477{478SmiNode *p;479480p = n;481n = smiGetFirstChildNode(n);482while (n != NULL) {483switch (n->nodekind) {484case SMI_NODEKIND_SCALAR:485case SMI_NODEKIND_COLUMN:486print_stype(n);487break;488case SMI_NODEKIND_COMPLIANCE:489case SMI_NODEKIND_GROUP:490save_node(n);491return;492default:493break;494}495n = smiGetNextChildNode(n);496}497498save_node(p);499}500501int502main(int argc, char *argv[])503{504int opt;505int flags;506SmiModule **mods;507char *name;508SmiNode *n, *last;509u_int level;510long u;511char *end;512513smiInit(NULL);514515while ((opt = getopt(argc, argv, "c:Eeh")) != -1)516switch (opt) {517518case 'c':519errno = 0;520u = strtol(optarg, &end, 10);521if (errno != 0)522err(1, "argument to -c");523if (*end != '\0')524err(1, "%s: not a number", optarg);525if (u < 0 || u > 5)526err(1, "%s: out of range", optarg);527cut = (u_int)u;528break;529530case 'E':531do_typedef = 'E';532break;533534case 'e':535do_typedef = 'e';536break;537538case 'h':539fprintf(stderr, usgtxt);540exit(0);541}542543argc -= optind;544argv += optind;545546flags = smiGetFlags();547flags |= SMI_FLAG_ERRORS;548smiSetFlags(flags);549550mods = malloc(sizeof(mods[0]) * argc);551if (mods == NULL)552err(1, NULL);553554for (opt = 0; opt < argc; opt++) {555if ((name = smiLoadModule(argv[opt])) == NULL)556err(1, "%s: cannot load", argv[opt]);557mods[opt] = smiGetModule(name);558}559level = 0;560last = NULL;561for (opt = 0; opt < argc; opt++) {562if (mods[opt] == NULL) /* smiGetModule failed above */563continue;564n = smiGetFirstNode(mods[opt], SMI_NODEKIND_ANY);565if (n == NULL)566continue;567for (;;) {568if (do_typedef == 0) {569level = open_node(n, level, &last);570print_it(n, level);571last = n;572} else573print_typdefs(n);574575if (last_node == NULL ||576(n = smiGetNextNode(last_node, SMI_NODEKIND_ANY))577== NULL)578break;579}580}581if (last != NULL && do_typedef == 0)582level = close_node(last->oidlen - 1, level - 1);583else if (do_typedef != 0)584tdefs_cleanup();585586return (0);587}588589590