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