xref: /freebsd/contrib/bsnmp/gensnmpdef/gensnmpdef.c (revision d37ea99837e6ad50837fd9fe1771ddf1c3ba6002)
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