gensnmpdef.c revision 128237
1221828Sgrehan/* 2221828Sgrehan * Copyright (c) 2004 3221828Sgrehan * Hartmut Brandt. 4221828Sgrehan * All rights reserved. 5221828Sgrehan * 6221828Sgrehan * Author: Harti Brandt <harti@freebsd.org> 7221828Sgrehan * 8221828Sgrehan * Redistribution of this software and documentation and use in source and 9221828Sgrehan * binary forms, with or without modification, are permitted provided that 10221828Sgrehan * the following conditions are met: 11221828Sgrehan * 12221828Sgrehan * 1. Redistributions of source code or documentation must retain the above 13221828Sgrehan * copyright notice, this list of conditions and the following disclaimer. 14221828Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 15221828Sgrehan * notice, this list of conditions and the following disclaimer in the 16221828Sgrehan * documentation and/or other materials provided with the distribution. 17221828Sgrehan * 3. Neither the name of the author nor the names of its contributors 18221828Sgrehan * may be used to endorse or promote products derived from this software 19221828Sgrehan * without specific prior written permission. 20221828Sgrehan * 21221828Sgrehan * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR 22221828Sgrehan * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 23221828Sgrehan * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 24221828Sgrehan * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 25221828Sgrehan * THE AUTHOR OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26221828Sgrehan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27221828Sgrehan * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 28221828Sgrehan * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29221828Sgrehan * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30221828Sgrehan * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 31221828Sgrehan * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32221828Sgrehan * 33221828Sgrehan * $Begemot: bsnmp/gensnmpdef/gensnmpdef.c,v 1.2 2004/04/14 09:54:51 novo Exp $ 34221828Sgrehan */ 35256072Sneel#include <stdio.h> 36256072Sneel#include <stdlib.h> 37256072Sneel#include <string.h> 38256072Sneel#include <unistd.h> 39221828Sgrehan#include <errno.h> 40#include <err.h> 41#include <assert.h> 42#include <smi.h> 43 44static const char usgtxt[] = 45"Usage: gensnmpdef [-h] [-c <cut>] MIB [MIB ...]\n" 46"Options:\n" 47" -c specify the number of initial sub-oids to cut from the oids\n" 48" -h print this help\n" 49"MIBs are searched according to the libsmi(3) search rules and can\n" 50"be specified either by path or module name\n"; 51 52static SmiNode *last_node; 53static u_int cut = 3; 54 55static void print_node(SmiNode *n, u_int level); 56 57static void 58save_node(SmiNode *n) 59{ 60 if (n != NULL) 61 last_node = n; 62} 63 64static void 65pindent(u_int level) 66{ 67 if (level >= cut) 68 printf("%*s", (level - cut) * 2, ""); 69} 70 71static void 72print_name(SmiNode *n) 73{ 74 char *p; 75 76 for (p = n->name; *p != '\0'; p++) { 77 if (*p == '-') 78 printf("_"); 79 else 80 printf("%c", *p); 81 } 82} 83 84static u_int 85close_node(u_int n, u_int level) 86{ 87 while (n--) { 88 pindent(level); 89 level--; 90 if (level >= cut) 91 printf(")\n"); 92 } 93 return (level); 94} 95 96static u_int 97open_node(const SmiNode *n, u_int level, SmiNode **last) 98{ 99 SmiNode *n1; 100 u_int i; 101 102 if (*last != NULL) { 103 for (i = 0; i < (*last)->oidlen - 1; i++) { 104 if (i >= n->oidlen) { 105 level = close_node((*last)->oidlen - 106 n->oidlen, level); 107 break; 108 } 109 if ((*last)->oid[i] != n->oid[i]) 110 break; 111 } 112 if (i < (*last)->oidlen - 1) 113 level = close_node((*last)->oidlen - 1 - i, 114 level - 1) + 1; 115 } 116 117 while (level < n->oidlen - 1) { 118 if (level >= cut) { 119 pindent(level); 120 printf("(%u", n->oid[level]); 121 n1 = smiGetNodeByOID(level + 1, n->oid); 122 printf(" "); 123 print_name(n1); 124 printf("\n"); 125 } 126 level++; 127 } 128 return (level); 129} 130 131static const char *const type_names[] = { 132 [SMI_BASETYPE_UNKNOWN] = "UNKNOWN_TYPE", 133 [SMI_BASETYPE_INTEGER32] = "INTEGER", 134 [SMI_BASETYPE_OCTETSTRING] = "OCTETSTRING", 135 [SMI_BASETYPE_OBJECTIDENTIFIER] = "OID", 136 [SMI_BASETYPE_UNSIGNED32] = "UNSIGNED32", 137 [SMI_BASETYPE_INTEGER64] = "INTEGER64", 138 [SMI_BASETYPE_UNSIGNED64] = "UNSIGNED64", 139 [SMI_BASETYPE_FLOAT32] = "FLOAT32", 140 [SMI_BASETYPE_FLOAT64] = "FLOAT64", 141 [SMI_BASETYPE_FLOAT128] = "FLOAT128", 142 [SMI_BASETYPE_ENUM] = "INTEGER", 143 [SMI_BASETYPE_BITS] = "BITS", 144}; 145 146static const char *const type_map[] = { 147 "Gauge32", "GAUGE", 148 "Gauge", "GAUGE", 149 "TimeTicks", "TIMETICKS", 150 "Counter32", "COUNTER", 151 "Counter", "COUNTER", 152 "Counter64", "COUNTER64", 153 "Integer32", "INTEGER32", 154 "IpAddress", "IPADDRESS", 155 NULL 156}; 157 158static void 159print_type(SmiNode *n) 160{ 161 SmiType *type; 162 u_int m; 163 164 type = smiGetNodeType(n); 165 assert(type != NULL); 166 167 if (type->name != NULL) { 168 for (m = 0; type_map[m] != NULL; m += 2) 169 if (strcmp(type_map[m], type->name) == 0) { 170 printf("%s", type_map[m + 1]); 171 return; 172 } 173 } 174 printf("%s", type_names[type->basetype]); 175} 176 177static void 178print_access(SmiAccess a) 179{ 180 if (a == SMI_ACCESS_READ_ONLY) 181 printf(" GET"); 182 else if (a == SMI_ACCESS_READ_WRITE) 183 printf(" GET SET"); 184} 185 186static void 187print_scalar(SmiNode *n, u_int level) 188{ 189 SmiNode *p; 190 191 assert (n->nodekind == SMI_NODEKIND_SCALAR); 192 193 save_node(n); 194 195 pindent(level); 196 printf("(%u ", n->oid[level]); 197 print_name(n); 198 printf(" "); 199 print_type(n); 200 201 /* generate the operation from the parent node name */ 202 p = smiGetParentNode(n); 203 printf(" op_%s", p->name); 204 205 print_access(n->access); 206 207 printf(")\n"); 208} 209 210static void 211print_notification(SmiNode *n, u_int level) 212{ 213 214 assert (n->nodekind == SMI_NODEKIND_NOTIFICATION); 215 216 save_node(n); 217 218 pindent(level); 219 printf("(%u ", n->oid[level]); 220 print_name(n); 221 printf(" OID"); 222 223 printf(" op_%s)\n", n->name); 224} 225 226static void 227print_col(SmiNode *n, u_int level) 228{ 229 assert (n->nodekind == SMI_NODEKIND_COLUMN); 230 231 save_node(n); 232 233 pindent(level); 234 printf("(%u ", n->oid[level]); 235 print_name(n); 236 printf(" "); 237 print_type(n); 238 print_access(n->access); 239 printf(")\n"); 240} 241 242static void 243print_index(SmiNode *row) 244{ 245 SmiElement *e; 246 247 e = smiGetFirstElement(row); 248 while (e != NULL) { 249 printf(" "); 250 print_type(smiGetElementNode(e)); 251 e = smiGetNextElement(e); 252 } 253} 254 255static void 256print_table(SmiNode *n, u_int level) 257{ 258 SmiNode *row, *col, *rel; 259 260 assert (n->nodekind == SMI_NODEKIND_TABLE); 261 262 save_node(n); 263 264 pindent(level); 265 printf("(%u ", n->oid[level]); 266 print_name(n); 267 printf("\n"); 268 269 row = smiGetFirstChildNode(n); 270 if (row->nodekind != SMI_NODEKIND_ROW) 271 errx(1, "%s: kind %u, not row", __func__, row->nodekind); 272 273 save_node(n); 274 275 pindent(level + 1); 276 printf("(%u ", row->oid[level + 1]); 277 print_name(row); 278 printf(" :"); 279 280 /* index */ 281 rel = smiGetRelatedNode(row); 282 switch (row->indexkind) { 283 284 case SMI_INDEX_INDEX: 285 print_index(row); 286 break; 287 288 case SMI_INDEX_AUGMENT: 289 if (rel == NULL) 290 errx(1, "%s: cannot find augemented table", row->name); 291 print_index(rel); 292 break; 293 294 default: 295 errx(1, "%s: cannot handle index kind %u", row->name, 296 row->indexkind); 297 } 298 299 printf(" op_%s", n->name); 300 printf("\n"); 301 302 col = smiGetFirstChildNode(row); 303 while (col != NULL) { 304 print_col(col, level + 2); 305 col = smiGetNextChildNode(col); 306 } 307 pindent(level + 1); 308 printf(")\n"); 309 310 pindent(level); 311 printf(")\n"); 312} 313 314static void 315print_it(SmiNode *n, u_int level) 316{ 317 switch (n->nodekind) { 318 319 case SMI_NODEKIND_NODE: 320 print_node(n, level); 321 break; 322 323 case SMI_NODEKIND_SCALAR: 324 print_scalar(n, level); 325 break; 326 327 case SMI_NODEKIND_TABLE: 328 print_table(n, level); 329 break; 330 331 case SMI_NODEKIND_COMPLIANCE: 332 case SMI_NODEKIND_GROUP: 333 save_node(n); 334 break; 335 336 case SMI_NODEKIND_NOTIFICATION: 337 print_notification(n, level); 338 break; 339 340 default: 341 errx(1, "cannot handle %u nodes", n->nodekind); 342 } 343} 344 345static void 346print_node(SmiNode *n, u_int level) 347{ 348 assert (n->nodekind == SMI_NODEKIND_NODE); 349 350 save_node(n); 351 352 pindent(level); 353 printf("(%u ", n->oid[level]); 354 print_name(n); 355 printf("\n"); 356 357 n = smiGetFirstChildNode(n); 358 while (n != NULL) { 359 print_it(n, level + 1); 360 n = smiGetNextChildNode(n); 361 } 362 pindent(level); 363 printf(")\n"); 364} 365 366int 367main(int argc, char *argv[]) 368{ 369 int opt; 370 int flags; 371 SmiModule **mods; 372 char *name; 373 SmiNode *n, *last; 374 u_int level; 375 long u; 376 char *end; 377 378 smiInit(NULL); 379 380 while ((opt = getopt(argc, argv, "c:h")) != -1) 381 switch (opt) { 382 383 case 'c': 384 errno = 0; 385 u = strtol(optarg, &end, 10); 386 if (errno != 0) 387 err(1, "argument to -c"); 388 if (*end != '\0') 389 err(1, "%s: not a number", optarg); 390 if (u < 0 || u > 5) 391 err(1, "%s: out of range", optarg); 392 cut = (u_int)u; 393 break; 394 395 case 'h': 396 fprintf(stderr, usgtxt); 397 exit(0); 398 } 399 400 argc -= optind; 401 argv += optind; 402 403 flags = smiGetFlags(); 404 flags |= SMI_FLAG_ERRORS; 405 smiSetFlags(flags); 406 407 mods = malloc(sizeof(mods[0]) * argc); 408 if (mods == NULL) 409 err(1, NULL); 410 411 for (opt = 0; opt < argc; opt++) { 412 if ((name = smiLoadModule(argv[opt])) == NULL) 413 err(1, "%s: cannot load", argv[opt]); 414 mods[opt] = smiGetModule(name); 415 } 416 level = 0; 417 last = NULL; 418 for (opt = 0; opt < argc; opt++) { 419 n = smiGetFirstNode(mods[opt], SMI_NODEKIND_ANY); 420 for (;;) { 421 level = open_node(n, level, &last); 422 print_it(n, level); 423 last = n; 424 425 if (last_node == NULL || 426 (n = smiGetNextNode(last_node, SMI_NODEKIND_ANY)) 427 == NULL) 428 break; 429 } 430 } 431 level = close_node(last->oidlen - 1, level - 1); 432 return (0); 433} 434