1 /* 2 * Copyright (c) 2004 3 * Hartmut Brandt. 4 * All rights reserved. 5 * 6 * Author: Harti Brandt <harti@freebsd.org> 7 * 8 * Redistribution of this software and documentation and use in source and 9 * binary forms, with or without modification, are permitted provided that 10 * the following conditions are met: 11 * 12 * 1. Redistributions of source code or documentation must retain the above 13 * copyright notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the author nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR 22 * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 23 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 24 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 25 * THE AUTHOR OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 28 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 31 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 * $Begemot: bsnmp/gensnmpdef/gensnmpdef.c,v 1.2 2004/04/14 09:54:51 novo Exp $ 34 */ 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <unistd.h> 39 #include <errno.h> 40 #include <err.h> 41 #include <assert.h> 42 #include <smi.h> 43 44 static 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 52 static SmiNode *last_node; 53 static u_int cut = 3; 54 55 static void print_node(SmiNode *n, u_int level); 56 57 static void 58 save_node(SmiNode *n) 59 { 60 if (n != NULL) 61 last_node = n; 62 } 63 64 static void 65 pindent(u_int level) 66 { 67 if (level >= cut) 68 printf("%*s", (level - cut) * 2, ""); 69 } 70 71 static void 72 print_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 84 static u_int 85 close_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 96 static u_int 97 open_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 131 static 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 146 static 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 158 static void 159 print_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 177 static void 178 print_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 186 static void 187 print_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 210 static void 211 print_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 226 static void 227 print_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 242 static void 243 print_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 255 static void 256 print_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 314 static void 315 print_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 345 static void 346 print_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 366 int 367 main(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