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