Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/bsnmp/gensnmpdef/gensnmpdef.c
39478 views
1
/*
2
* Copyright (C) 2004-2006
3
* Hartmut Brandt.
4
* All rights reserved.
5
*
6
* Author: Harti Brandt <[email protected]>
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: gensnmpdef.c 383 2006-05-30 07:40:49Z brandt_h $
30
*/
31
#include <sys/queue.h>
32
33
#include <stdio.h>
34
#include <stdlib.h>
35
#include <string.h>
36
#include <unistd.h>
37
#include <errno.h>
38
#include <err.h>
39
#include <assert.h>
40
#include <smi.h>
41
42
static const char usgtxt[] =
43
"Usage: gensnmpdef [-hEe] [-c <cut>] MIB [MIB ...]\n"
44
"Options:\n"
45
" -c specify the number of initial sub-oids to cut from the oids\n"
46
" -E extract named enum types. Print a typedef for all enums defined\n"
47
" in syntax clauses of normal objects. Suppress normal output.\n"
48
" -e extract unnamed enum types. Print a typedef for all enums defined\n"
49
" as textual conventions. Suppress normal output.\n"
50
" -h print this help\n"
51
"MIBs are searched according to the libsmi(3) search rules and can\n"
52
"be specified either by path or module name\n";
53
54
static SmiNode *last_node;
55
static u_int cut = 3;
56
57
struct tdef {
58
char *name;
59
SLIST_ENTRY(tdef) link;
60
};
61
62
static SLIST_HEAD(, tdef) tdefs = SLIST_HEAD_INITIALIZER(tdefs);
63
static int do_typedef = 0;
64
65
static void print_node(SmiNode *n, u_int level);
66
67
static void
68
save_node(SmiNode *n)
69
{
70
if (n != NULL)
71
last_node = n;
72
}
73
74
static void
75
pindent(u_int level)
76
{
77
if (level >= cut)
78
printf("%*s", (level - cut) * 2, "");
79
}
80
81
static void
82
print_name(SmiNode *n)
83
{
84
char *p;
85
86
for (p = n->name; *p != '\0'; p++) {
87
if (*p == '-')
88
printf("_");
89
else
90
printf("%c", *p);
91
}
92
}
93
94
static u_int
95
close_node(u_int n, u_int level)
96
{
97
while (n--) {
98
pindent(level);
99
level--;
100
if (level >= cut)
101
printf(")\n");
102
}
103
return (level);
104
}
105
106
static u_int
107
open_node(const SmiNode *n, u_int level, SmiNode **last)
108
{
109
SmiNode *n1;
110
u_int i;
111
112
if (*last != NULL) {
113
for (i = 0; i < (*last)->oidlen - 1; i++) {
114
if (i >= n->oidlen) {
115
level = close_node((*last)->oidlen -
116
n->oidlen, level);
117
break;
118
}
119
if ((*last)->oid[i] != n->oid[i])
120
break;
121
}
122
if (i < (*last)->oidlen - 1)
123
level = close_node((*last)->oidlen - 1 - i,
124
level - 1) + 1;
125
}
126
127
while (level < n->oidlen - 1) {
128
if (level >= cut) {
129
n1 = smiGetNodeByOID(level + 1, n->oid);
130
if (n1 == NULL)
131
continue;
132
pindent(level);
133
printf("(%u", n->oid[level]);
134
printf(" ");
135
print_name(n1);
136
printf("\n");
137
}
138
level++;
139
}
140
return (level);
141
}
142
143
static const char *const type_names[] = {
144
[SMI_BASETYPE_UNKNOWN] = "UNKNOWN_TYPE",
145
[SMI_BASETYPE_INTEGER32] = "INTEGER",
146
[SMI_BASETYPE_OCTETSTRING] = "OCTETSTRING",
147
[SMI_BASETYPE_OBJECTIDENTIFIER] = "OID",
148
[SMI_BASETYPE_UNSIGNED32] = "UNSIGNED32",
149
[SMI_BASETYPE_INTEGER64] = "INTEGER64",
150
[SMI_BASETYPE_UNSIGNED64] = "UNSIGNED64",
151
[SMI_BASETYPE_FLOAT32] = "FLOAT32",
152
[SMI_BASETYPE_FLOAT64] = "FLOAT64",
153
[SMI_BASETYPE_FLOAT128] = "FLOAT128",
154
[SMI_BASETYPE_ENUM] = "ENUM",
155
[SMI_BASETYPE_BITS] = "BITS",
156
};
157
158
static const char *const type_map[] = {
159
"Gauge32", "GAUGE",
160
"Gauge", "GAUGE",
161
"TimeTicks", "TIMETICKS",
162
"Counter32", "COUNTER",
163
"Counter", "COUNTER",
164
"Counter64", "COUNTER64",
165
"Integer32", "INTEGER32",
166
"IpAddress", "IPADDRESS",
167
NULL
168
};
169
170
static void
171
print_enum(SmiType *t)
172
{
173
SmiNamedNumber *nnum;
174
175
printf(" (");
176
for (nnum = smiGetFirstNamedNumber(t); nnum != NULL;
177
nnum = smiGetNextNamedNumber(nnum))
178
printf(" %ld %s", nnum->value.value.integer32, nnum->name);
179
printf(" )");
180
}
181
182
static void
183
print_type(SmiNode *n)
184
{
185
SmiType *type;
186
u_int m;
187
188
type = smiGetNodeType(n);
189
assert(type != NULL);
190
191
if (type->name != NULL) {
192
for (m = 0; type_map[m] != NULL; m += 2)
193
if (strcmp(type_map[m], type->name) == 0) {
194
printf("%s", type_map[m + 1]);
195
return;
196
}
197
}
198
printf("%s", type_names[type->basetype]);
199
200
if (type->basetype == SMI_BASETYPE_ENUM ||
201
type->basetype == SMI_BASETYPE_BITS)
202
print_enum(type);
203
204
else if (type->basetype == SMI_BASETYPE_OCTETSTRING &&
205
type->name != NULL)
206
printf(" | %s", type->name);
207
}
208
209
static void
210
print_access(SmiAccess a)
211
{
212
if (a == SMI_ACCESS_READ_ONLY)
213
printf(" GET");
214
else if (a == SMI_ACCESS_READ_WRITE)
215
printf(" GET SET");
216
}
217
218
static void
219
print_scalar(SmiNode *n, u_int level)
220
{
221
SmiNode *p;
222
223
assert (n->nodekind == SMI_NODEKIND_SCALAR);
224
225
save_node(n);
226
227
pindent(level);
228
printf("(%u ", n->oid[level]);
229
print_name(n);
230
printf(" ");
231
print_type(n);
232
233
/* generate the operation from the parent node name */
234
p = smiGetParentNode(n);
235
printf(" op_%s", p->name);
236
237
print_access(n->access);
238
239
printf(")\n");
240
}
241
242
static void
243
print_notification(SmiNode *n, u_int level)
244
{
245
246
assert (n->nodekind == SMI_NODEKIND_NOTIFICATION);
247
248
save_node(n);
249
250
pindent(level);
251
printf("(%u ", n->oid[level]);
252
print_name(n);
253
printf(" OID");
254
255
printf(" op_%s)\n", n->name);
256
}
257
258
static void
259
print_col(SmiNode *n, u_int level)
260
{
261
assert (n->nodekind == SMI_NODEKIND_COLUMN);
262
263
save_node(n);
264
265
pindent(level);
266
printf("(%u ", n->oid[level]);
267
print_name(n);
268
printf(" ");
269
print_type(n);
270
print_access(n->access);
271
printf(")\n");
272
}
273
274
static void
275
print_index(SmiNode *row)
276
{
277
SmiElement *e;
278
279
e = smiGetFirstElement(row);
280
while (e != NULL) {
281
printf(" ");
282
print_type(smiGetElementNode(e));
283
e = smiGetNextElement(e);
284
}
285
}
286
287
static void
288
print_table(SmiNode *n, u_int level)
289
{
290
SmiNode *row, *col, *rel;
291
292
assert (n->nodekind == SMI_NODEKIND_TABLE);
293
294
save_node(n);
295
296
pindent(level);
297
printf("(%u ", n->oid[level]);
298
print_name(n);
299
printf("\n");
300
301
row = smiGetFirstChildNode(n);
302
if (row->nodekind != SMI_NODEKIND_ROW)
303
errx(1, "%s: kind %u, not row", __func__, row->nodekind);
304
305
save_node(n);
306
307
pindent(level + 1);
308
printf("(%u ", row->oid[level + 1]);
309
print_name(row);
310
printf(" :");
311
312
/* index */
313
rel = smiGetRelatedNode(row);
314
switch (row->indexkind) {
315
316
case SMI_INDEX_INDEX:
317
print_index(row);
318
break;
319
320
case SMI_INDEX_AUGMENT:
321
if (rel == NULL)
322
errx(1, "%s: cannot find augemented table", row->name);
323
print_index(rel);
324
break;
325
326
default:
327
errx(1, "%s: cannot handle index kind %u", row->name,
328
row->indexkind);
329
}
330
331
printf(" op_%s", n->name);
332
printf("\n");
333
334
col = smiGetFirstChildNode(row);
335
while (col != NULL) {
336
print_col(col, level + 2);
337
col = smiGetNextChildNode(col);
338
}
339
pindent(level + 1);
340
printf(")\n");
341
342
pindent(level);
343
printf(")\n");
344
}
345
346
static void
347
print_it(SmiNode *n, u_int level)
348
{
349
switch (n->nodekind) {
350
351
case SMI_NODEKIND_NODE:
352
print_node(n, level);
353
break;
354
355
case SMI_NODEKIND_SCALAR:
356
print_scalar(n, level);
357
break;
358
359
case SMI_NODEKIND_TABLE:
360
print_table(n, level);
361
break;
362
363
case SMI_NODEKIND_COMPLIANCE:
364
case SMI_NODEKIND_GROUP:
365
save_node(n);
366
break;
367
368
case SMI_NODEKIND_NOTIFICATION:
369
print_notification(n, level);
370
break;
371
372
default:
373
errx(1, "cannot handle %u nodes", n->nodekind);
374
}
375
}
376
377
static void
378
print_node(SmiNode *n, u_int level)
379
{
380
assert (n->nodekind == SMI_NODEKIND_NODE);
381
382
save_node(n);
383
384
pindent(level);
385
printf("(%u ", n->oid[level]);
386
print_name(n);
387
printf("\n");
388
389
n = smiGetFirstChildNode(n);
390
while (n != NULL) {
391
print_it(n, level + 1);
392
n = smiGetNextChildNode(n);
393
}
394
pindent(level);
395
printf(")\n");
396
}
397
398
static void
399
save_typdef(char *name)
400
{
401
struct tdef *t;
402
403
t = calloc(1, sizeof(struct tdef));
404
if (t == NULL)
405
err(1, NULL);
406
407
t->name = name;
408
SLIST_INSERT_HEAD(&tdefs, t, link);
409
}
410
411
static void
412
tdefs_cleanup(void)
413
{
414
struct tdef *t;
415
416
while ((t = SLIST_FIRST(&tdefs)) != NULL) {
417
SLIST_REMOVE_HEAD(&tdefs, link);
418
free(t);
419
}
420
}
421
422
static void
423
print_enum_typedef(SmiType *t)
424
{
425
SmiNamedNumber *nnum;
426
427
for (nnum = smiGetFirstNamedNumber(t); nnum != NULL;
428
nnum = smiGetNextNamedNumber(nnum)) {
429
printf("\t%ld %s\n" , nnum->value.value.integer32, nnum->name);
430
}
431
}
432
433
static void
434
print_stype(SmiNode *n)
435
{
436
SmiType *type;
437
struct tdef *t = NULL;
438
439
type = smiGetNodeType(n);
440
assert(type != NULL);
441
442
if (type->basetype == SMI_BASETYPE_ENUM) {
443
if (do_typedef == 'e' && type->name != NULL) {
444
SLIST_FOREACH(t, &tdefs, link) {
445
if (strcmp(t->name, type->name) == 0)
446
return;
447
}
448
save_typdef(type->name);
449
printf("typedef %s ENUM (\n", type->name);
450
} else if (do_typedef == 'E' && type->name == NULL)
451
printf("typedef %sType ENUM (\n", n->name);
452
else
453
return;
454
455
print_enum_typedef(type);
456
printf(")\n\n");
457
458
} else if (type->basetype == SMI_BASETYPE_BITS) {
459
if (do_typedef == 'e' && type->name != NULL) {
460
SLIST_FOREACH(t, &tdefs, link) {
461
if (strcmp(t->name, type->name) == 0)
462
return;
463
}
464
save_typdef(type->name);
465
printf("typedef %s BITS (\n", type->name);
466
} else if (do_typedef == 'E' && type->name == NULL)
467
printf("typedef %sType BITS (\n", n->name);
468
else
469
return;
470
471
print_enum_typedef(type);
472
printf(")\n\n");
473
}
474
}
475
476
static void
477
print_typdefs(SmiNode *n)
478
{
479
SmiNode *p;
480
481
p = n;
482
n = smiGetFirstChildNode(n);
483
while (n != NULL) {
484
switch (n->nodekind) {
485
case SMI_NODEKIND_SCALAR:
486
case SMI_NODEKIND_COLUMN:
487
print_stype(n);
488
break;
489
case SMI_NODEKIND_COMPLIANCE:
490
case SMI_NODEKIND_GROUP:
491
save_node(n);
492
return;
493
default:
494
break;
495
}
496
n = smiGetNextChildNode(n);
497
}
498
499
save_node(p);
500
}
501
502
int
503
main(int argc, char *argv[])
504
{
505
int opt;
506
int flags;
507
SmiModule **mods;
508
char *name;
509
SmiNode *n, *last;
510
u_int level;
511
long u;
512
char *end;
513
514
smiInit(NULL);
515
516
while ((opt = getopt(argc, argv, "c:Eeh")) != -1)
517
switch (opt) {
518
519
case 'c':
520
errno = 0;
521
u = strtol(optarg, &end, 10);
522
if (errno != 0)
523
err(1, "argument to -c");
524
if (*end != '\0')
525
err(1, "%s: not a number", optarg);
526
if (u < 0 || u > 5)
527
err(1, "%s: out of range", optarg);
528
cut = (u_int)u;
529
break;
530
531
case 'E':
532
do_typedef = 'E';
533
break;
534
535
case 'e':
536
do_typedef = 'e';
537
break;
538
539
case 'h':
540
fprintf(stderr, usgtxt);
541
exit(0);
542
}
543
544
argc -= optind;
545
argv += optind;
546
547
flags = smiGetFlags();
548
flags |= SMI_FLAG_ERRORS;
549
smiSetFlags(flags);
550
551
mods = malloc(sizeof(mods[0]) * argc);
552
if (mods == NULL)
553
err(1, NULL);
554
555
for (opt = 0; opt < argc; opt++) {
556
if ((name = smiLoadModule(argv[opt])) == NULL)
557
err(1, "%s: cannot load", argv[opt]);
558
mods[opt] = smiGetModule(name);
559
}
560
level = 0;
561
last = NULL;
562
for (opt = 0; opt < argc; opt++) {
563
if (mods[opt] == NULL) /* smiGetModule failed above */
564
continue;
565
n = smiGetFirstNode(mods[opt], SMI_NODEKIND_ANY);
566
if (n == NULL)
567
continue;
568
for (;;) {
569
if (do_typedef == 0) {
570
level = open_node(n, level, &last);
571
print_it(n, level);
572
last = n;
573
} else
574
print_typdefs(n);
575
576
if (last_node == NULL ||
577
(n = smiGetNextNode(last_node, SMI_NODEKIND_ANY))
578
== NULL)
579
break;
580
}
581
}
582
if (last != NULL && do_typedef == 0)
583
level = close_node(last->oidlen - 1, level - 1);
584
else if (do_typedef != 0)
585
tdefs_cleanup();
586
587
return (0);
588
}
589
590