1 /*
2  * smi.c --
3  *
4  *      Interface Implementation of libsmi.
5  *
6  * Copyright (c) 1999 Frank Strauss, Technical University of Braunschweig.
7  *
8  * See the file "COPYING" for information on usage and redistribution
9  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10  *
11  * @(#) $Id: smi.c 8071 2008-04-17 11:14:46Z schoenw $
12  */
13 
14 #include <config.h>
15 
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <ctype.h>
20 #include <sys/types.h>
21 #ifdef HAVE_UNISTD_H
22 #include <unistd.h>
23 #endif
24 #ifdef HAVE_PWD_H
25 #include <pwd.h>
26 #endif
27 
28 #include "smi.h"
29 #include "data.h"
30 #include "error.h"
31 #include "util.h"
32 #include "snprintf.h"
33 
34 #ifdef BACKEND_SMI
35 #include "scanner-smi.h"
36 #include "parser-smi.h"
37 #endif
38 
39 #ifdef BACKEND_SMING
40 #include "scanner-sming.h"
41 #include "parser-sming.h"
42 #endif
43 
44 #ifdef HAVE_DMALLOC_H
45 #include <dmalloc.h>
46 #endif
47 
48 
49 
50 #ifndef MIN
51 #define MIN(a, b)       ((a) < (b) ? (a) : (b))
52 #define MAX(a, b)       ((a) < (b) ? (b) : (a))
53 #endif
54 
55 
56 
57 const char *smi_library_version = SMI_LIBRARY_VERSION;
58 const char *smi_version_string = SMI_VERSION_STRING;
59 
60 Handle *smiHandle = NULL;
61 
62 
63 
64 /*
65  * Internal functions.
66  */
67 
getModulenameAndName(const char * arg1,const char * arg2,char ** module,char ** name)68 static void getModulenameAndName(const char *arg1, const char *arg2,
69 				 char **module, char **name)
70 {
71     char	    *p;
72     int		    l;
73 
74     if ((!arg1) && (!arg2)) {
75 	*module = NULL;
76 	*name = NULL;
77     } else if (!arg2) {
78 	if (isupper((int)arg1[0])) {
79 	    if ((p = strstr(arg1, "::"))) {
80 		/* SMIng style module/label separator */
81 		*name = smiStrdup(&p[2]);
82 		l = strcspn(arg1, "::");
83 		*module = smiStrndup(arg1, l);
84 	    } else if ((p = strchr(arg1, '!'))) {
85 		/* old scotty style module/label separator */
86 		*name = smiStrdup(&p[1]);
87 		l = strcspn(arg1, "!");
88 		*module = smiStrndup(arg1, l);
89 	    } else if ((p = strchr(arg1, '.'))) {
90 		/* SMIv1/v2 style module/label separator */
91 		*name = smiStrdup(&p[1]);
92 		l = strcspn(arg1, ".");
93 		*module = smiStrndup(arg1, l);
94 	    } else {
95 		*name = smiStrdup(arg1);
96 		*module = smiStrdup("");
97 	    }
98 	} else {
99 	    *name = smiStrdup(arg1);
100 	    *module = smiStrdup("");
101 	}
102     } else if (!arg1) {
103 	if (isupper((int)arg2[0])) {
104 	    if ((p = strstr(arg2, "::"))) {
105 		/* SMIng style module/label separator */
106 		*name = smiStrdup(&p[2]);
107 		l = strcspn(arg2, "::");
108 		*module = smiStrndup(arg2, l);
109 	    } else if ((p = strchr(arg2, '!'))) {
110 		/* old scotty style module/label separator */
111 		*name = smiStrdup(&p[1]);
112 		l = strcspn(arg2, "!");
113 		*module = smiStrndup(arg2, l);
114 	    } else if ((p = strchr(arg2, '.'))) {
115 		/* SMIv1/v2 style module/label separator */
116 		*name = smiStrdup(&p[1]);
117 		l = strcspn(arg2, ".");
118 		*module = smiStrndup(arg2, l);
119 	    } else {
120 		*name = smiStrdup(arg2);
121 		*module = smiStrdup("");
122 	    }
123 	} else {
124 	    *name = smiStrdup(arg2);
125 	    *module = smiStrdup("");
126 	}
127     } else {
128 	*module = smiStrdup(arg1);
129 	*name = smiStrdup(arg2);
130     }
131 }
132 
133 
134 
getNode(unsigned int oidlen,SmiSubid oid[])135 static Node *getNode(unsigned int oidlen, SmiSubid oid[])
136 {
137     Node *nodePtr, *parentPtr;
138     unsigned int i;
139 
140     for(nodePtr = smiHandle->rootNodePtr, i=0; i < oidlen; i++) {
141 	parentPtr = nodePtr;
142 	nodePtr = findNodeByParentAndSubid(parentPtr, oid[i]);
143 	if (!nodePtr) {
144 	    return parentPtr;
145 	}
146     }
147 
148     return nodePtr;
149 }
150 
151 
152 
getNextChildObject(Node * startNodePtr,Module * modulePtr,SmiNodekind nodekind)153 static Object *getNextChildObject(Node *startNodePtr, Module *modulePtr,
154 				  SmiNodekind nodekind)
155 {
156     Node   *nodePtr;
157     Object *objectPtr = NULL;
158 
159     if (!startNodePtr || !modulePtr)
160 	return NULL;
161 
162     for (nodePtr = startNodePtr; nodePtr; nodePtr = nodePtr->nextPtr) {
163 	for (objectPtr = nodePtr->firstObjectPtr; objectPtr;
164 	     objectPtr = objectPtr->nextSameNodePtr) {
165 	    if (((!modulePtr) || (objectPtr->modulePtr == modulePtr)) &&
166 		((nodekind == SMI_NODEKIND_ANY) ||
167 		 (nodekind & objectPtr->export.nodekind))) {
168 		break;
169 	    }
170 	}
171 	if (objectPtr) break;
172 	objectPtr = getNextChildObject(nodePtr->firstChildPtr,
173 				       modulePtr, nodekind);
174 	if (objectPtr) break;
175     }
176 
177     return objectPtr;
178 }
179 
180 
181 
182 /*
183  * Interface Functions.
184  */
185 
smiInit(const char * tag)186 int smiInit(const char *tag)
187 {
188     char *p, *pp, *tag2;
189 #ifdef HAVE_PWD_H
190     struct passwd *pw;
191 #endif
192 
193     smiHandle = findHandleByName(tag);
194     if (smiHandle) {
195 	return 0;
196     }
197     smiHandle = addHandle(tag);
198 
199     smiDepth = 0;
200 
201     smiHandle->errorLevel = DEFAULT_ERRORLEVEL;
202     smiHandle->errorHandler = smiErrorHandler;
203 #if !defined(_MSC_VER)
204     smiHandle->cache = NULL;
205     smiHandle->cacheProg = NULL;
206 #endif
207 
208     if (smiInitData()) {
209 	return -1;
210     }
211 
212     /*
213      * Setup the SMI MIB module search path:
214      *  1. set to builtin DEFAULT_SMIPATH
215      *  2. read global config file if present (append/prepend/replace)
216      *  3. read user config file if present (append/prepend/replace)
217      *  4. evaluate SMIPATH env-var if set (append/prepend/replace)
218      */
219 
220     /* 1. set to builtin DEFAULT_SMIPATH */
221     smiHandle->path = smiStrdup(DEFAULT_SMIPATH);
222 
223     tag2 = smiStrdup(tag);
224     if (tag2) tag2 = strtok(tag2, ":");
225     if (tag2) {
226 	/* 2. read global config file if present (append/prepend/replace) */
227 	smiReadConfig(DEFAULT_GLOBALCONFIG, tag2);
228 #ifdef HAVE_PWD_H
229 	pw = getpwuid(getuid());
230 	if (pw && pw->pw_dir) {
231 	    /* 3. read user config file if present (append/prepend/replace) */
232 	    smiAsprintf(&p, "%s%c%s",
233 			pw->pw_dir, DIR_SEPARATOR, DEFAULT_USERCONFIG);
234 	    smiReadConfig(p, tag2);
235 	    smiFree(p);
236 	}
237 #endif
238     }
239     smiFree(tag2);
240 
241     /* 4. evaluate SMIPATH env-var if set (append/prepend/replace) */
242     p = getenv("SMIPATH");
243     if (p) {
244 	if (p[0] == PATH_SEPARATOR) {
245 	    smiAsprintf(&pp, "%s%s", smiHandle->path, p);
246 	    smiFree(smiHandle->path);
247 	    smiHandle->path = pp;
248 	} else if (p[strlen(p)-1] == PATH_SEPARATOR) {
249 	    smiAsprintf(&pp, "%s%s", p, smiHandle->path);
250 	    smiFree(smiHandle->path);
251 	    smiHandle->path = pp;
252 	} else {
253 	    smiHandle->path = smiStrdup(p);
254 	}
255     }
256 
257     if (!smiHandle->path) {
258 	return -1;
259     }
260 
261     return 0;
262 }
263 
264 
265 
smiExit()266 void smiExit()
267 {
268     if (!smiHandle)
269 	return;
270 
271     smiFreeData();
272 
273     smiFree(smiHandle->path);
274 #if !defined(_MSC_VER)
275     smiFree(smiHandle->cache);
276     smiFree(smiHandle->cacheProg);
277 #endif
278 
279     removeHandle(smiHandle);
280 
281     smiHandle = NULL;
282     return;
283 }
284 
285 
286 
smiGetPath()287 char *smiGetPath()
288 {
289     if (smiHandle->path) {
290 	return smiStrdup(smiHandle->path);
291     } else {
292 	return NULL;
293     }
294 }
295 
296 
297 
smiSetPath(const char * s)298 int smiSetPath(const char *s)
299 {
300     char *s2;
301 
302     if (!smiHandle) smiInit(NULL);
303 
304     if (!s) {
305 	smiFree(smiHandle->path);
306 	smiHandle->path = NULL;
307 	return 0;
308     }
309 
310     s2 = smiStrdup(s);
311     if (s2) {
312 	smiFree(smiHandle->path);
313 	smiHandle->path = s2;
314 	return 0;
315     } else {
316 	return -1;
317     }
318 
319 }
320 
321 
322 
smiSetSeverity(char * pattern,int severity)323 void smiSetSeverity(char *pattern, int severity)
324 {
325     smiSetErrorSeverity(pattern, severity);
326 }
327 
328 
329 
smiReadConfig(const char * filename,const char * tag)330 int smiReadConfig(const char *filename, const char *tag)
331 {
332     FILE *file;
333     char buf[201];
334     char *cmd, *arg, *s;
335 
336     file = fopen(filename, "r");
337     if (file) {
338 	while (!feof(file)) {
339 	    if (!fgets(buf, 200, file)) continue;
340 	    if ((!strlen(buf)) || (buf[0] == '#')) continue;
341 	    cmd = strtok(buf, " \t\n\r");
342 	    if (!cmd) continue;
343 	    if (cmd[0] == '#') continue;
344 	    if (cmd[strlen(cmd)-1] == ':') {
345 		if (!tag) continue;
346 		cmd[strlen(cmd)-1] = 0;
347 		if (strcmp(cmd, tag)) continue;
348 		cmd = strtok(NULL, " \t\n\r");
349 	    }
350 	    arg = strtok(NULL, " \t\n\r");
351 	    if (!strcmp(cmd, "load")) {
352 		smiLoadModule(arg);
353 	    } else if (!strcmp(cmd, "path")) {
354 		if (arg) {
355 		    if (arg[0] == PATH_SEPARATOR) {
356 			smiAsprintf(&s, "%s%s", smiHandle->path, arg);
357 			smiFree(smiHandle->path);
358 			smiHandle->path = s;
359 		    } else if (arg[strlen(arg)-1] == PATH_SEPARATOR) {
360 			smiAsprintf(&s, "%s%s", arg, smiHandle->path);
361 			smiFree(smiHandle->path);
362 			smiHandle->path = s;
363 		    } else {
364 			smiHandle->path = smiStrdup(arg);
365 		    }
366 		}
367 	    } else if (!strcmp(cmd, "cache")) {
368 #if !defined(_MSC_VER)
369 		smiFree(smiHandle->cache);
370 		smiFree(smiHandle->cacheProg);
371 #endif
372 		if (arg && strcmp(arg, "off")) {
373 #if !defined(_MSC_VER)
374 		    smiHandle->cache = smiStrdup(arg);
375 		    arg = strtok(NULL, "\n\r");
376 		    smiHandle->cacheProg = smiStrdup(arg);
377 #else
378 		    smiPrintError(NULL, ERR_CACHE_CONFIG_NOT_SUPPORTED,
379 				  filename);
380 #endif
381 		}
382 	    } else if (!strcmp(cmd, "level")) {
383 		smiSetErrorLevel(atoi(arg));
384 	    } else if (!strcmp(cmd, "hide")) {
385 		smiSetSeverity(arg, 9);
386 	    } else {
387 		smiPrintError(NULL, ERR_UNKNOWN_CONFIG_CMD, cmd, filename);
388 	    }
389 	}
390 	fclose(file);
391 	return 0;
392     }
393     return -1;
394 }
395 
396 
397 
smiIsLoaded(const char * module)398 int smiIsLoaded(const char *module)
399 {
400     if (!module)
401 	return 0;
402 
403     return isInView(module);
404 }
405 
406 
407 
smiLoadModule(const char * module)408 char *smiLoadModule(const char *module)
409 {
410     Module *modulePtr;
411 
412     if (!smiHandle) smiInit(NULL);
413 
414     if (smiIsPath(module)) {
415 
416 	modulePtr = loadModule(module, NULL);
417 
418 	if (modulePtr) {
419 	    if (!isInView(modulePtr->export.name)) {
420 		addView(modulePtr->export.name);
421 	    }
422 	    return modulePtr->export.name;
423 	} else {
424 	    return NULL;
425 	}
426 
427     } else {
428 
429 	if ((modulePtr = findModuleByName(module))) {
430 	    /* already loaded. */
431 	    if (!isInView(module)) {
432 		addView(module);
433 	    }
434 	    return modulePtr->export.name;
435 	} else {
436 	    if ((modulePtr = loadModule(module, NULL))) {
437 		if (!isInView(module)) {
438 		    addView(module);
439 		}
440 		return modulePtr->export.name;
441 	    } else {
442 		return NULL;
443 	    }
444 	}
445     }
446 }
447 
448 
449 
smiSetErrorLevel(int level)450 void smiSetErrorLevel(int level)
451 {
452     if (!smiHandle) smiInit(NULL);
453 
454     smiHandle->errorLevel = level;
455 }
456 
457 
458 
smiSetFlags(int userflags)459 void smiSetFlags(int userflags)
460 {
461     if (!smiHandle) smiInit(NULL);
462 
463     smiHandle->flags = (smiHandle->flags & ~SMI_FLAG_MASK) | userflags;
464 }
465 
466 
467 
smiGetFlags()468 int smiGetFlags()
469 {
470     if (!smiHandle) smiInit(NULL);
471 
472     return smiHandle->flags & SMI_FLAG_MASK;
473 }
474 
475 
476 
smiGetModule(const char * module)477 SmiModule *smiGetModule(const char *module)
478 {
479     Module	      *modulePtr;
480 
481     if (!module) {
482 	return NULL;
483     }
484 
485     modulePtr = findModuleByName(module);
486 
487     if (!modulePtr) {
488 	modulePtr = loadModule(module, NULL);
489     }
490 
491     return &modulePtr->export;
492 }
493 
494 
495 
smiGetFirstModule()496 SmiModule *smiGetFirstModule()
497 {
498     Module	      *modulePtr;
499 
500     for (modulePtr = smiHandle->firstModulePtr;
501 	 modulePtr && modulePtr->export.name &&
502 	     (strlen(modulePtr->export.name) == 0);
503 	 modulePtr = modulePtr->nextPtr);
504 
505     return &modulePtr->export;
506 }
507 
508 
509 
smiGetNextModule(SmiModule * smiModulePtr)510 SmiModule *smiGetNextModule(SmiModule *smiModulePtr)
511 {
512     Module	      *modulePtr;
513 
514     if (!smiModulePtr) {
515 	return NULL;
516     }
517 
518 
519     for (modulePtr = ((Module *)smiModulePtr)->nextPtr;
520 	 modulePtr && modulePtr->export.name &&
521 	     (strlen(modulePtr->export.name) == 0);
522 	 modulePtr = modulePtr->nextPtr);
523 
524     return &modulePtr->export;
525 }
526 
527 
528 
smiGetFirstImport(SmiModule * smiModulePtr)529 SmiImport *smiGetFirstImport(SmiModule *smiModulePtr)
530 {
531     if (!smiModulePtr) {
532 	return NULL;
533     }
534 
535     return &((Module *)smiModulePtr)->firstImportPtr->export;
536 }
537 
538 
539 
smiGetNextImport(SmiImport * smiImportPtr)540 SmiImport *smiGetNextImport(SmiImport *smiImportPtr)
541 {
542     if (!smiImportPtr) {
543 	return NULL;
544     }
545 
546     return &((Import *)smiImportPtr)->nextPtr->export;
547 }
548 
549 
550 
smiIsImported(SmiModule * smiModulePtr,SmiModule * importedModulePtr,char * importedName)551 int smiIsImported(SmiModule *smiModulePtr,
552 		  SmiModule *importedModulePtr,
553 		  char *importedName)
554 {
555     Import	   *importPtr;
556     Module	   *modulePtr;
557     char	   *importedModule;
558 
559     if ((!smiModulePtr) || (!importedName)) {
560 	return 0;
561     }
562 
563     modulePtr = (Module *)smiModulePtr;
564 
565     if (importedModulePtr) {
566 	importedModule = importedModulePtr->name;
567     } else {
568 	importedModule = NULL;
569     }
570 
571     for (importPtr = modulePtr->firstImportPtr; importPtr;
572 	 importPtr = importPtr->nextPtr) {
573 	if ((!strcmp(importedName, importPtr->export.name)) &&
574 	    ((!importedModule) ||
575 	     (!strcmp(importedModule, importPtr->export.module)))) {
576 	    return 1;
577 	}
578     }
579 
580     return 0;
581 }
582 
583 
584 
smiGetFirstRevision(SmiModule * smiModulePtr)585 SmiRevision *smiGetFirstRevision(SmiModule *smiModulePtr)
586 {
587     if (!smiModulePtr) {
588 	return NULL;
589     }
590 
591     return &((Module *)smiModulePtr)->firstRevisionPtr->export;
592 }
593 
594 
595 
smiGetNextRevision(SmiRevision * smiRevisionPtr)596 SmiRevision *smiGetNextRevision(SmiRevision *smiRevisionPtr)
597 {
598     if (!smiRevisionPtr) {
599 	return NULL;
600     }
601 
602     return &((Revision *)smiRevisionPtr)->nextPtr->export;
603 }
604 
605 
606 
smiGetRevisionLine(SmiRevision * smiRevisionPtr)607 int smiGetRevisionLine(SmiRevision *smiRevisionPtr)
608 {
609     return ((Revision *)smiRevisionPtr)->line;
610 }
611 
612 
613 
smiGetType(SmiModule * smiModulePtr,char * type)614 SmiType *smiGetType(SmiModule *smiModulePtr, char *type)
615 {
616     Type	    *typePtr = NULL;
617     Module	    *modulePtr = NULL;
618     char	    *module2, *type2;
619 
620     if (!type) {
621 	return NULL;
622     }
623 
624     modulePtr = (Module *)smiModulePtr;
625 
626     getModulenameAndName(smiModulePtr ? smiModulePtr->name : NULL, type,
627 			 &module2, &type2);
628 
629     if (!modulePtr && module2 && strlen(module2)) {
630 	if (!(modulePtr = findModuleByName(module2))) {
631 	    modulePtr = loadModule(module2, NULL);
632 	}
633     }
634 
635     if (modulePtr) {
636 	typePtr = findTypeByModuleAndName(modulePtr, type2);
637     } else {
638 	typePtr = findTypeByName(type2);
639     }
640 
641     smiFree(module2);
642     smiFree(type2);
643 
644     if (!typePtr ||
645 	typePtr->export.basetype == SMI_BASETYPE_UNKNOWN) {
646 	return NULL;
647     }
648 
649     return &typePtr->export;
650 }
651 
652 
653 
smiGetFirstType(SmiModule * smiModulePtr)654 SmiType *smiGetFirstType(SmiModule *smiModulePtr)
655 {
656     Type *typePtr;
657 
658     if (!smiModulePtr) {
659 	return NULL;
660     }
661 
662     for (typePtr = ((Module *)smiModulePtr)->firstTypePtr; typePtr;
663 	 typePtr = typePtr->nextPtr) {
664 	/* loop until we found a `real' type */
665 	if (typePtr->export.name &&
666 	    typePtr->export.basetype != SMI_BASETYPE_UNKNOWN) {
667 	    break;
668 	}
669     }
670 
671     return &typePtr->export;
672 }
673 
674 
675 
smiGetNextType(SmiType * smiTypePtr)676 SmiType *smiGetNextType(SmiType *smiTypePtr)
677 {
678     Type *typePtr;
679 
680     if (!smiTypePtr) {
681 	return NULL;
682     }
683 
684     for (typePtr = ((Type *)smiTypePtr)->nextPtr; typePtr;
685 	 typePtr = typePtr->nextPtr) {
686 	/* loop until we found a `real' type */
687 	if (typePtr->export.name &&
688 	    typePtr->export.basetype != SMI_BASETYPE_UNKNOWN) {
689 	    break;
690 	}
691     }
692 
693     return &typePtr->export;
694 }
695 
696 
smiGetParentType(SmiType * smiTypePtr)697 SmiType *smiGetParentType(SmiType *smiTypePtr)
698 {
699     Type *typePtr;
700 
701     if (!smiTypePtr) {
702 	return NULL;
703     }
704 
705     typePtr = ((Type *)smiTypePtr)->parentPtr;
706 
707     if (!typePtr ||
708 	typePtr->export.basetype == SMI_BASETYPE_UNKNOWN) {
709 	return NULL;
710     }
711 
712     return &typePtr->export;
713 }
714 
715 
716 
smiGetTypeModule(SmiType * smiTypePtr)717 SmiModule *smiGetTypeModule(SmiType *smiTypePtr)
718 {
719     return &((Type *)smiTypePtr)->modulePtr->export;
720 }
721 
smiGetTypeLine(SmiType * smiTypePtr)722 int smiGetTypeLine(SmiType *smiTypePtr)
723 {
724     return ((Type *)smiTypePtr)->line;
725 }
726 
727 
728 
smiGetFirstNamedNumber(SmiType * smiTypePtr)729 SmiNamedNumber *smiGetFirstNamedNumber(SmiType *smiTypePtr)
730 {
731     Type    *typePtr;
732 
733     typePtr = (Type *)smiTypePtr;
734 
735     if ((!typePtr) || (!typePtr->listPtr) ||
736 	((typePtr->export.basetype != SMI_BASETYPE_ENUM) &&
737 	 (typePtr->export.basetype != SMI_BASETYPE_BITS) &&
738 	 (typePtr->export.basetype != SMI_BASETYPE_POINTER))) {
739 	return NULL;
740     }
741 
742     return &((NamedNumber *)typePtr->listPtr->ptr)->export;
743 }
744 
745 
746 
smiGetNextNamedNumber(SmiNamedNumber * smiNamedNumberPtr)747 SmiNamedNumber *smiGetNextNamedNumber(SmiNamedNumber *smiNamedNumberPtr)
748 {
749     Type  *typePtr;
750     List  *listPtr;
751 
752     if (!smiNamedNumberPtr) {
753 	return NULL;
754     }
755 
756     typePtr = ((NamedNumber *)smiNamedNumberPtr)->typePtr;
757 
758 
759     if ((!typePtr) || (!typePtr->listPtr) ||
760 	((typePtr->export.basetype != SMI_BASETYPE_ENUM) &&
761 	 (typePtr->export.basetype != SMI_BASETYPE_BITS))) {
762 	return NULL;
763     }
764 
765     for (listPtr = typePtr->listPtr; listPtr; listPtr = listPtr->nextPtr) {
766 	if (((NamedNumber *)(listPtr->ptr))->export.name ==
767 	                                               smiNamedNumberPtr->name)
768 	    break;
769     }
770 
771     if ((!listPtr) || (!listPtr->nextPtr)) {
772 	return NULL;
773     }
774 
775     return &((NamedNumber *)listPtr->nextPtr->ptr)->export;
776 }
777 
smiGetAttributeFirstNamedNumber(SmiAttribute * smiAttributePtr)778 SmiNamedNumber *smiGetAttributeFirstNamedNumber(SmiAttribute *smiAttributePtr)
779 {
780     Attribute    *attributePtr;
781 
782     attributePtr = (Attribute *)smiAttributePtr;
783 
784     if ((!attributePtr) || (!attributePtr->listPtr) ||
785 	((attributePtr->export.basetype != SMI_BASETYPE_ENUM) &&
786 	 (attributePtr->export.basetype != SMI_BASETYPE_BITS) &&
787 	 (attributePtr->export.basetype != SMI_BASETYPE_POINTER))) {
788 	return NULL;
789     }
790 
791     return &((NamedNumber *)attributePtr->listPtr->ptr)->export;
792 }
793 
794 
795 
smiGetAttributeNextNamedNumber(SmiNamedNumber * smiNamedNumberPtr)796 SmiNamedNumber *smiGetAttributeNextNamedNumber(SmiNamedNumber *smiNamedNumberPtr)
797 {
798     Attribute  *attributePtr;
799     List  *listPtr;
800 
801     if (!smiNamedNumberPtr) {
802 	return NULL;
803     }
804 
805     attributePtr = (Attribute*)(((NamedNumber *)smiNamedNumberPtr)->typePtr);
806 
807 
808     if ((!attributePtr) || (!attributePtr->listPtr) ||
809 	((attributePtr->export.basetype != SMI_BASETYPE_ENUM) &&
810 	 (attributePtr->export.basetype != SMI_BASETYPE_BITS))) {
811 	return NULL;
812     }
813 
814     for (listPtr = attributePtr->listPtr; listPtr; listPtr = listPtr->nextPtr) {
815 	if (((NamedNumber *)(listPtr->ptr))->export.name ==
816 	                                               smiNamedNumberPtr->name)
817 	    break;
818     }
819 
820     if ((!listPtr) || (!listPtr->nextPtr)) {
821 	return NULL;
822     }
823 
824     return &((NamedNumber *)listPtr->nextPtr->ptr)->export;
825 }
826 
smiGetFirstRange(SmiType * smiTypePtr)827 SmiRange *smiGetFirstRange(SmiType *smiTypePtr)
828 {
829     Type    *typePtr;
830 
831     typePtr = (Type *)smiTypePtr;
832 
833     if ((!typePtr) || (!typePtr->listPtr) ||
834 	(typePtr->export.basetype == SMI_BASETYPE_ENUM) ||
835 	(typePtr->export.basetype == SMI_BASETYPE_BITS)) {
836 	return NULL;
837     }
838 
839     return &((Range *)typePtr->listPtr->ptr)->export;
840 }
841 
842 
843 
smiGetNextRange(SmiRange * smiRangePtr)844 SmiRange *smiGetNextRange(SmiRange *smiRangePtr)
845 {
846     Type  *typePtr;
847     List  *listPtr;
848 
849     if (!smiRangePtr) {
850 	return NULL;
851     }
852 
853     typePtr = ((Range *)smiRangePtr)->typePtr;
854 
855     if ((!typePtr) || (!typePtr->listPtr) ||
856 	(typePtr->export.basetype == SMI_BASETYPE_ENUM) ||
857 	(typePtr->export.basetype == SMI_BASETYPE_BITS)) {
858 	return NULL;
859     }
860 
861     for (listPtr = typePtr->listPtr; listPtr; listPtr = listPtr->nextPtr) {
862 	if (!memcmp(&((Range *)listPtr->ptr)->export.minValue,
863 		    &smiRangePtr->minValue, sizeof(struct SmiValue)))
864 	    break;
865     }
866 
867     if ((!listPtr) || (!listPtr->nextPtr)) {
868 	return NULL;
869     }
870 
871     return &((Range *)listPtr->nextPtr->ptr)->export;
872 }
873 
smiGetAttributeFirstRange(SmiAttribute * smiAttributePtr)874 SmiRange *smiGetAttributeFirstRange(SmiAttribute *smiAttributePtr)
875 {
876     Attribute    *attributePtr;
877 
878     attributePtr = (Attribute *)smiAttributePtr;
879 
880     if ((!attributePtr) || (!attributePtr->listPtr) ||
881 	(attributePtr->export.basetype == SMI_BASETYPE_ENUM) ||
882 	(attributePtr->export.basetype == SMI_BASETYPE_BITS)) {
883 	return NULL;
884     }
885 
886     return &((Range *)attributePtr->listPtr->ptr)->export;
887 }
888 
889 
890 
smiGetAttributeNextRange(SmiRange * smiRangePtr)891 SmiRange *smiGetAttributeNextRange(SmiRange *smiRangePtr)
892 {
893     Attribute  *attributePtr;
894     List  *listPtr;
895 
896     if (!smiRangePtr) {
897 	return NULL;
898     }
899 
900     attributePtr = (Attribute*)((Range *)smiRangePtr)->typePtr;
901 
902     if ((!attributePtr) || (!attributePtr->listPtr) ||
903 	(attributePtr->export.basetype == SMI_BASETYPE_ENUM) ||
904 	(attributePtr->export.basetype == SMI_BASETYPE_BITS)) {
905 	return NULL;
906     }
907 
908     for (listPtr = attributePtr->listPtr; listPtr; listPtr = listPtr->nextPtr) {
909 	if (!memcmp(&((Range *)listPtr->ptr)->export.minValue,
910 		    &smiRangePtr->minValue, sizeof(struct SmiValue)))
911 	    break;
912     }
913 
914     if ((!listPtr) || (!listPtr->nextPtr)) {
915 	return NULL;
916     }
917 
918     return &((Range *)listPtr->nextPtr->ptr)->export;
919 }
920 
921 
smiGetFirstIdentity(SmiModule * smiModulePtr)922 SmiIdentity *smiGetFirstIdentity(SmiModule *smiModulePtr)
923 {
924 	if (!smiModulePtr) {
925 	return NULL;
926     }
927 
928     return ((Module *)smiModulePtr)->firstIdentityPtr ?
929 	&((Module *)smiModulePtr)->firstIdentityPtr->export : NULL;
930 
931 }
932 
smiGetNextIdentity(SmiIdentity * smiIdentityPtr)933 SmiIdentity *smiGetNextIdentity(SmiIdentity *smiIdentityPtr)
934 {
935     if (!smiIdentityPtr) {
936 	return NULL;
937     }
938 
939     return ((Identity *)smiIdentityPtr)->nextPtr ?
940 	&((Identity *)smiIdentityPtr)->nextPtr->export : NULL;
941 }
942 
smiGetIdentityModule(SmiIdentity * smiIdentityPtr)943 SmiModule *smiGetIdentityModule(SmiIdentity *smiIdentityPtr)
944 {
945     return &((Identity *)smiIdentityPtr)->modulePtr->export;
946 }
947 
smiGetParentIdentity(SmiIdentity * smiIdentityPtr)948 SmiIdentity *smiGetParentIdentity(SmiIdentity *smiIdentityPtr)
949 {
950     return (SmiIdentity*)(((Identity *)smiIdentityPtr)->parentPtr);
951 }
952 
smiGetIdentity(SmiModule * smiModulePtr,char * identity)953 SmiIdentity *smiGetIdentity(SmiModule *smiModulePtr, char *identity)
954 {
955 
956 	if (!smiModulePtr) {
957 	return NULL;
958     }
959     else
960     {
961     	SmiIdentity *ide;
962 
963     	for(ide = smiGetFirstIdentity(smiModulePtr);
964     		ide;
965     		ide = smiGetNextIdentity(ide))
966     			if(!strncmp(ide->name,identity,64))return ide;
967 
968     	return NULL;
969     }
970 
971 }
972 
smiGetIdentityLine(SmiIdentity * smiIdentityPtr)973 int smiGetIdentityLine(SmiIdentity *smiIdentityPtr)
974 {
975     return ((Identity *)smiIdentityPtr)->line;
976 }
977 
978 
smiGetFirstClass(SmiModule * smiModulePtr)979 SmiClass *smiGetFirstClass(SmiModule *smiModulePtr)
980 {
981 	if (!smiModulePtr) {
982 	return NULL;
983     }
984 
985     return ((Module *)smiModulePtr)->firstClassPtr ?
986 	&((Module *)smiModulePtr)->firstClassPtr->export : NULL;
987 
988 }
989 
smiGetNextClass(SmiClass * smiClassPtr)990 SmiClass *smiGetNextClass(SmiClass *smiClassPtr)
991 {
992     if (!smiClassPtr) {
993 	return NULL;
994     }
995 
996     return ((Class *)smiClassPtr)->nextPtr ?
997 	&((Class *)smiClassPtr)->nextPtr->export : NULL;
998 }
999 
smiGetClassModule(SmiClass * smiClassPtr)1000 SmiModule *smiGetClassModule(SmiClass *smiClassPtr)
1001 {
1002     return &((Class *)smiClassPtr)->modulePtr->export;
1003 }
1004 
smiGetParentClass(SmiClass * smiClassPtr)1005 SmiClass *smiGetParentClass(SmiClass *smiClassPtr)
1006 {
1007     return (SmiClass*)(((Class *)smiClassPtr)->parentPtr);
1008 }
1009 
smiGetClass(SmiModule * smiModulePtr,char * class)1010 SmiClass *smiGetClass(SmiModule *smiModulePtr, char *class)
1011 {
1012 
1013 	if (!smiModulePtr) {
1014 	return NULL;
1015     }
1016     else
1017     {
1018     	SmiClass *cl;
1019 
1020     	for(cl = smiGetFirstClass(smiModulePtr);
1021     		cl;
1022     		cl = smiGetNextClass(cl))
1023     			if(!strncmp(cl->name,class,64))return cl;
1024 
1025     	return NULL;
1026     }
1027 
1028 }
1029 
smiGetClassLine(SmiClass * smiClassPtr)1030 int smiGetClassLine(SmiClass *smiClassPtr)
1031 {
1032     return ((Class *)smiClassPtr)->line;
1033 }
1034 
smiGetFirstAttribute(SmiClass * smiClassPtr)1035 SmiAttribute *smiGetFirstAttribute(SmiClass *smiClassPtr)
1036 {
1037     Attribute *attributePtr;
1038 
1039     if (!smiClassPtr) {
1040 	return NULL;
1041     }
1042 
1043   	attributePtr = ((Class *)smiClassPtr)->firstAttributePtr;
1044 
1045     return &attributePtr->export;
1046 }
1047 
smiGetNextAttribute(SmiAttribute * smiTypePtr)1048  SmiAttribute *smiGetNextAttribute( SmiAttribute *smiTypePtr)
1049 {
1050     Attribute *attributePtr;
1051 
1052     if (!smiTypePtr) {
1053 	return NULL;
1054     }
1055 
1056     attributePtr = ((Attribute *)smiTypePtr)->nextPtr;
1057 
1058     return &attributePtr->export;
1059 }
1060 
smiGetAttribute(SmiClass * smiClassPtr,char * attribute)1061 SmiAttribute *smiGetAttribute(SmiClass *smiClassPtr, char *attribute)
1062 {
1063     Attribute *attributePtr;
1064 
1065     if (! smiClassPtr) {
1066 	return NULL;
1067     }
1068 
1069     attributePtr = ((Class *)smiClassPtr)->firstAttributePtr;
1070 
1071     for (attributePtr = ((Class *)smiClassPtr)->firstAttributePtr;
1072 	 attributePtr; attributePtr = attributePtr->nextPtr)
1073     {
1074 	if (!strncmp(attributePtr->export.name, attribute,64)) {
1075 	    return &attributePtr->export;
1076 	}
1077     }
1078 
1079     /*
1080      * attribute might belong to the parent so check parent if
1081      * attribute not found
1082      */
1083 
1084     smiClassPtr = smiGetParentClass(smiClassPtr);
1085     attributePtr = (Attribute*)smiGetAttribute(smiClassPtr , attribute);
1086 
1087     return &attributePtr->export;
1088 }
1089 
smiGetAttributeParentType(SmiAttribute * smiAttributePtr)1090 SmiType *smiGetAttributeParentType(SmiAttribute *smiAttributePtr)
1091 {
1092     Type *parentTypePtr;
1093 
1094     if (! smiAttributePtr) {
1095 	return NULL;
1096     }
1097 
1098     parentTypePtr = ((Attribute*)smiAttributePtr)->parentTypePtr;
1099 
1100     return (parentTypePtr) ? &parentTypePtr->export : NULL;
1101 }
1102 
smiGetAttributeParentClass(SmiAttribute * smiAttributePtr)1103 SmiClass *smiGetAttributeParentClass( SmiAttribute *smiAttributePtr)
1104 {
1105     Class *parentClassPtr;
1106 
1107     if (! smiAttributePtr) {
1108 	return NULL;
1109     }
1110 
1111     parentClassPtr = ((Attribute*)smiAttributePtr)->parentClassPtr;
1112 
1113     return parentClassPtr ? &parentClassPtr->export : NULL;
1114 }
1115 
smiGetFirstUniqueAttribute(SmiClass * smiClassPtr)1116 SmiAttribute *smiGetFirstUniqueAttribute(SmiClass *smiClassPtr)
1117 {
1118     Class *classPtr;
1119 
1120     if (! smiClassPtr) {
1121 	return NULL;
1122     }
1123 
1124     classPtr = (Class*)smiClassPtr;
1125 
1126     if (! classPtr->uniqueList) {
1127 	return NULL;
1128     }
1129 
1130     if (classPtr->uniqueList->ptr == classPtr) {
1131 	return NULL; /* scalar class */
1132     }
1133 
1134     return (SmiAttribute*)(classPtr->uniqueList->ptr);
1135 }
1136 
smiGetNextUniqueAttribute(SmiAttribute * smiTypePtr)1137 SmiAttribute *smiGetNextUniqueAttribute( SmiAttribute *smiTypePtr)
1138 {
1139     Class *classPtr;
1140     List  *listPtr;
1141 
1142     if (! smiTypePtr) {
1143 	return NULL;
1144     }
1145 
1146     classPtr = ((Attribute*)smiTypePtr)->classPtr;
1147 
1148     if (classPtr && classPtr->uniqueList) {
1149 	for (listPtr=classPtr->uniqueList;listPtr; listPtr=listPtr->nextPtr) {
1150 	    if (&((Attribute*)(listPtr->ptr))->export ==  smiTypePtr) {
1151 		if (listPtr->nextPtr) {
1152 		    return &((Attribute*)(listPtr->nextPtr->ptr))->export;
1153 		}
1154 	    }
1155 	}
1156     }
1157     return NULL;
1158 }
1159 
1160 
1161 
smiGetAttributeLine(SmiAttribute * smiAttributePtr)1162 int smiGetAttributeLine(SmiAttribute *smiAttributePtr)
1163 {
1164     return ((Attribute *)smiAttributePtr)->line;
1165 }
1166 
1167 
1168 
smiIsClassScalar(SmiClass * smiClassPtr)1169 int smiIsClassScalar(SmiClass *smiClassPtr)
1170 {
1171     Class *classPtr;
1172 
1173     if (! smiClassPtr) {
1174 	return 0;
1175     }
1176 
1177     classPtr = (Class*)smiClassPtr;
1178 
1179     if (! classPtr->uniqueList) {
1180 	return 0;
1181     }
1182 
1183     return (classPtr->uniqueList->ptr == classPtr);
1184 }
1185 
1186 
1187 
smiGetFirstEvent(SmiClass * smiClassPtr)1188 SmiEvent *smiGetFirstEvent(SmiClass *smiClassPtr)
1189 {
1190     Event *eventPtr;
1191 
1192     if (! smiClassPtr) {
1193 	return NULL;
1194     }
1195 
1196     eventPtr = ((Class *)smiClassPtr)->firstEventPtr;
1197     return &(eventPtr->export);
1198 }
1199 
1200 
1201 
smiGetNextEvent(SmiEvent * smiEventPtr)1202 SmiEvent *smiGetNextEvent(SmiEvent *smiEventPtr)
1203 {
1204     Event *eventPtr;
1205 
1206     if (! smiEventPtr) {
1207 	return NULL;
1208     }
1209 
1210     eventPtr = ((Event *)smiEventPtr)->nextPtr;
1211     return &eventPtr->export;
1212 }
1213 
1214 
1215 
smiGetEventLine(SmiEvent * smiEventPtr)1216 int smiGetEventLine(SmiEvent *smiEventPtr)
1217 {
1218     return ((Event *)smiEventPtr)->line;
1219 }
1220 
1221 
1222 
smiGetMacro(SmiModule * smiModulePtr,char * macro)1223 SmiMacro *smiGetMacro(SmiModule *smiModulePtr, char *macro)
1224 {
1225     Macro	    *macroPtr = NULL;
1226     Module	    *modulePtr = NULL;
1227     char	    *module2, *macro2;
1228 
1229     if (!macro) {
1230 	return NULL;
1231     }
1232 
1233     modulePtr = (Module *)smiModulePtr;
1234 
1235     getModulenameAndName(smiModulePtr ? smiModulePtr->name : NULL, macro,
1236 			 &module2, &macro2);
1237 
1238     if (!modulePtr && module2 && strlen(module2)) {
1239 	if (!(modulePtr = findModuleByName(module2))) {
1240 	    modulePtr = loadModule(module2, NULL);
1241 	}
1242     }
1243 
1244     if (modulePtr) {
1245 	macroPtr = findMacroByModuleAndName(modulePtr, macro2);
1246     } else {
1247 	macroPtr = findMacroByName(macro2);
1248     }
1249 
1250     smiFree(module2);
1251     smiFree(macro2);
1252     return macroPtr ? &macroPtr->export : NULL;
1253 }
1254 
1255 
1256 
smiGetFirstMacro(SmiModule * smiModulePtr)1257 SmiMacro *smiGetFirstMacro(SmiModule *smiModulePtr)
1258 {
1259     if (!smiModulePtr) {
1260 	return NULL;
1261     }
1262 
1263     return ((Module *)smiModulePtr)->firstMacroPtr ?
1264 	&((Module *)smiModulePtr)->firstMacroPtr->export : NULL;
1265 }
1266 
1267 
1268 
smiGetNextMacro(SmiMacro * smiMacroPtr)1269 SmiMacro *smiGetNextMacro(SmiMacro *smiMacroPtr)
1270 {
1271     if (!smiMacroPtr) {
1272 	return NULL;
1273     }
1274 
1275     return ((Macro *)smiMacroPtr)->nextPtr ?
1276 	&((Macro *)smiMacroPtr)->nextPtr->export : NULL;
1277 }
1278 
1279 
smiGetMacroModule(SmiMacro * smiMacroPtr)1280 SmiModule *smiGetMacroModule(SmiMacro *smiMacroPtr)
1281 {
1282     return &((Macro *)smiMacroPtr)->modulePtr->export;
1283 }
1284 
1285 
smiGetMacroLine(SmiMacro * smiMacroPtr)1286 int smiGetMacroLine(SmiMacro *smiMacroPtr)
1287 {
1288     return ((Macro *)smiMacroPtr)->line;
1289 }
1290 
1291 
smiGetNode(SmiModule * smiModulePtr,const char * node)1292 SmiNode *smiGetNode(SmiModule *smiModulePtr, const char *node)
1293 {
1294     Object	    *objectPtr = NULL;
1295     Module	    *modulePtr = NULL;
1296     Node            *nodePtr;
1297     char	    *module2, *node2, *p;
1298     unsigned int    oidlen;
1299     SmiSubid	    oid[128];
1300 
1301     if (!node) {
1302 	return NULL;
1303     }
1304 
1305     modulePtr = (Module *)smiModulePtr;
1306 
1307     getModulenameAndName(smiModulePtr ? smiModulePtr->name : NULL, node,
1308 			 &module2, &node2);
1309 
1310     if (!modulePtr && module2 && strlen(module2)) {
1311 	if (!(modulePtr = findModuleByName(module2))) {
1312 	    modulePtr = loadModule(module2, NULL);
1313 	}
1314     }
1315 
1316     if (isdigit((int)node2[0])) {
1317 	for (oidlen = 0, p = strtok(node2, ". "); p;
1318 	     oidlen++, p = strtok(NULL, ". ")) {
1319 	    oid[oidlen] = strtoul(p, NULL, 0);
1320 	}
1321 	nodePtr = getNode(oidlen, oid);
1322 	if (nodePtr) {
1323 	    if (modulePtr) {
1324 		objectPtr = findObjectByModuleAndNode(modulePtr, nodePtr);
1325 	    } else {
1326 		objectPtr = findObjectByNode(nodePtr);
1327 	    }
1328 	}
1329     } else {
1330 	p = strtok(node2, ". ");
1331 	if (modulePtr) {
1332 	    objectPtr = findObjectByModuleAndName(modulePtr, p);
1333 	} else {
1334 	    objectPtr = findObjectByName(p);
1335 	}
1336     }
1337 
1338     smiFree(module2);
1339     smiFree(node2);
1340     return objectPtr ? &objectPtr->export : NULL;
1341 }
1342 
1343 
1344 
smiGetNodeByOID(unsigned int oidlen,SmiSubid oid[])1345 SmiNode *smiGetNodeByOID(unsigned int oidlen, SmiSubid oid[])
1346 {
1347     Node            *nodePtr;
1348     Object	    *objectPtr;
1349 
1350     if (!oidlen) {
1351 	return NULL;
1352     }
1353 
1354     nodePtr = getNode(oidlen, oid);
1355 
1356     if (!nodePtr) {
1357 	return NULL;
1358     }
1359 
1360     objectPtr = findObjectByNode(nodePtr);
1361 
1362     return objectPtr ? &objectPtr->export : NULL;
1363 }
1364 
1365 
1366 
smiGetFirstNode(SmiModule * smiModulePtr,SmiNodekind nodekind)1367 SmiNode *smiGetFirstNode(SmiModule *smiModulePtr, SmiNodekind nodekind)
1368 {
1369     Module *modulePtr;
1370     Node   *nodePtr = NULL;
1371     Object *objectPtr;
1372 
1373     if (!smiModulePtr) {
1374 	return NULL;
1375     }
1376 
1377     modulePtr = (Module *)smiModulePtr;
1378 
1379     if (modulePtr && modulePtr->prefixNodePtr) {
1380 	/* start at the common oid prefix of this module */
1381 	nodePtr = modulePtr->prefixNodePtr;
1382     } else {
1383 	nodePtr = smiHandle->rootNodePtr->firstChildPtr;
1384     }
1385 
1386     do {
1387 	objectPtr = getNextChildObject(nodePtr, modulePtr, nodekind);
1388 
1389 	if (objectPtr)
1390 	    return &objectPtr->export;
1391 
1392 	if (nodePtr->firstChildPtr) {
1393 	    nodePtr = nodePtr->firstChildPtr;
1394 	} else if (nodePtr->nextPtr) {
1395 	    nodePtr = nodePtr->nextPtr;
1396 	} else {
1397 	    for (nodePtr = nodePtr->parentPtr;
1398 		 nodePtr && (nodePtr->parentPtr) && (!nodePtr->nextPtr);
1399 		 nodePtr = nodePtr->parentPtr);
1400 	    if (nodePtr) nodePtr = nodePtr->nextPtr;
1401 	}
1402     } while (nodePtr);
1403 
1404     return NULL;
1405 }
1406 
1407 
1408 
smiGetNextNode(SmiNode * smiNodePtr,SmiNodekind nodekind)1409 SmiNode *smiGetNextNode(SmiNode *smiNodePtr, SmiNodekind nodekind)
1410 {
1411     Module	      *modulePtr;
1412     Object	      *objectPtr;
1413     Node	      *nodePtr;
1414     int               i;
1415 
1416     if (!smiNodePtr) {
1417 	return NULL;
1418     }
1419 
1420     objectPtr = (Object *)smiNodePtr;
1421     nodePtr = objectPtr->nodePtr;
1422     modulePtr = objectPtr->modulePtr;
1423 
1424     if (!modulePtr) {
1425 	return NULL;
1426     }
1427 
1428     if (!nodePtr) {
1429 	return NULL;
1430     }
1431 
1432     do {
1433 	if (nodePtr->firstChildPtr) {
1434 	    nodePtr = nodePtr->firstChildPtr;
1435 	} else if (nodePtr->nextPtr) {
1436 	    nodePtr = nodePtr->nextPtr;
1437 	} else {
1438 	    for (nodePtr = nodePtr->parentPtr;
1439 		 (nodePtr->parentPtr) && (!nodePtr->nextPtr);
1440 		 nodePtr = nodePtr->parentPtr);
1441 	    nodePtr = nodePtr->nextPtr;
1442 	    /* did we move outside the common oid prefix of this module? */
1443 	    for (i = 0; i < modulePtr->prefixNodePtr->oidlen; i++)
1444 		if ((!nodePtr) || (!nodePtr->oid) ||
1445 		    (nodePtr->oid[i] != modulePtr->prefixNodePtr->oid[i]))
1446 		    return NULL;
1447 	}
1448 
1449 	objectPtr = getNextChildObject(nodePtr, modulePtr, nodekind);
1450 
1451 	if (objectPtr)
1452 	    return &objectPtr->export;
1453 
1454     } while (nodePtr);
1455 
1456     return NULL;
1457 }
1458 
1459 
1460 
smiGetParentNode(SmiNode * smiNodePtr)1461 SmiNode *smiGetParentNode(SmiNode *smiNodePtr)
1462 {
1463     Module	      *modulePtr;
1464     Object	      *objectPtr;
1465     Import	      *importPtr;
1466     Node	      *nodePtr;
1467 
1468     if (!smiNodePtr) {
1469 	return NULL;
1470     }
1471 
1472     objectPtr = (Object *)smiNodePtr;
1473     nodePtr = objectPtr->nodePtr;
1474     modulePtr = objectPtr->modulePtr;
1475 
1476     if (!nodePtr) {
1477 	return NULL;
1478     }
1479 
1480     if (nodePtr == smiHandle->rootNodePtr) {
1481 	return NULL;
1482     }
1483 
1484     nodePtr = nodePtr->parentPtr;
1485     if (! nodePtr) {
1486         return NULL;
1487     }
1488 
1489     /*
1490      * First, try to find a definition in the same module.
1491      */
1492     objectPtr = NULL;
1493     if (modulePtr) {
1494 	objectPtr = findObjectByModuleAndNode(modulePtr, nodePtr);
1495     }
1496 
1497     /*
1498      * If found, check if it's imported. In case, get the original definition.
1499      */
1500     if (objectPtr) {
1501 	importPtr = findImportByName(objectPtr->export.name,
1502 				     objectPtr->modulePtr);
1503 	if (importPtr) {
1504 	    objectPtr = findObjectByModulenameAndNode(importPtr->export.module,
1505 						      nodePtr);
1506 	} else {
1507 	    objectPtr = NULL;
1508 	}
1509     }
1510 
1511     /*
1512      * If not yet found, try to find any definition.
1513      */
1514     if (!objectPtr) {
1515 	objectPtr = findObjectByNode(nodePtr);
1516 
1517 	if ((!objectPtr) && (nodePtr->parentPtr)) {
1518 	    /* an implicitly created node, e.g. gaga.0 in an object
1519 	     * definition with oid == gaga.0.1.
1520 	     */
1521 	    objectPtr = addObject(SMI_UNKNOWN_LABEL,
1522 				  nodePtr->parentPtr, nodePtr->subid,
1523 				  0, NULL);
1524 	    objectPtr->nodePtr = nodePtr;
1525 	    objectPtr->modulePtr = modulePtr;
1526 	}
1527     }
1528 
1529     return objectPtr ? &objectPtr->export : NULL;
1530 }
1531 
1532 
1533 
smiGetRelatedNode(SmiNode * smiNodePtr)1534 SmiNode *smiGetRelatedNode(SmiNode *smiNodePtr)
1535 {
1536     if (!smiNodePtr) {
1537 	return NULL;
1538     }
1539 
1540     return &((Object *)smiNodePtr)->relatedPtr->export;
1541 }
1542 
1543 
1544 
smiGetFirstChildNode(SmiNode * smiNodePtr)1545 SmiNode *smiGetFirstChildNode(SmiNode *smiNodePtr)
1546 {
1547     Module	      *modulePtr;
1548     Object	      *objectPtr;
1549     Node	      *nodePtr;
1550 
1551     if (!smiNodePtr) {
1552 	return NULL;
1553     }
1554 
1555     objectPtr = (Object *)smiNodePtr;
1556     nodePtr = objectPtr->nodePtr;
1557     modulePtr = objectPtr->modulePtr;
1558 
1559     if (!nodePtr) {
1560 	return NULL;
1561     }
1562 
1563     nodePtr = nodePtr->firstChildPtr;
1564 
1565     if (!nodePtr) {
1566 	return NULL;
1567     }
1568 
1569     objectPtr = findObjectByModuleAndNode(modulePtr, nodePtr);
1570     if (!objectPtr) objectPtr = findObjectByNode(nodePtr);
1571 
1572     return objectPtr ? &objectPtr->export : NULL;
1573 }
1574 
1575 
1576 
smiGetNextChildNode(SmiNode * smiNodePtr)1577 SmiNode *smiGetNextChildNode(SmiNode *smiNodePtr)
1578 {
1579     Module	      *modulePtr;
1580     Object	      *objectPtr;
1581     Node	      *nodePtr;
1582 
1583     if (!smiNodePtr) {
1584 	return NULL;
1585     }
1586 
1587     objectPtr = (Object *)smiNodePtr;
1588     nodePtr = objectPtr->nodePtr;
1589     modulePtr = objectPtr->modulePtr;
1590 
1591     if (!nodePtr) {
1592 	return NULL;
1593     }
1594 
1595     nodePtr = nodePtr->nextPtr;
1596 
1597     if (!nodePtr) {
1598 	return NULL;
1599     }
1600 
1601     objectPtr = findObjectByModuleAndNode(modulePtr, nodePtr);
1602     if (!objectPtr) objectPtr = findObjectByNode(nodePtr);
1603 
1604     return objectPtr ? &objectPtr->export : NULL;
1605 }
1606 
1607 
1608 
smiGetModuleIdentityNode(SmiModule * smiModulePtr)1609 SmiNode *smiGetModuleIdentityNode(SmiModule *smiModulePtr)
1610 {
1611     if (!smiModulePtr) {
1612 	return NULL;
1613     }
1614 
1615     return &((Module *)smiModulePtr)->objectPtr->export;
1616 }
1617 
1618 
1619 
smiGetNodeModule(SmiNode * smiNodePtr)1620 SmiModule *smiGetNodeModule(SmiNode *smiNodePtr)
1621 {
1622     return &((Object *)smiNodePtr)->modulePtr->export;
1623 }
1624 
1625 
1626 
smiGetNodeType(SmiNode * smiNodePtr)1627 SmiType *smiGetNodeType(SmiNode *smiNodePtr)
1628 {
1629     Type *typePtr;
1630 
1631     typePtr = ((Object *)smiNodePtr)->typePtr;
1632 
1633     if (!typePtr ||
1634 	typePtr->export.basetype == SMI_BASETYPE_UNKNOWN) {
1635 	return NULL;
1636     }
1637 
1638     return &typePtr->export;
1639 }
1640 
1641 
1642 
smiGetNodeLine(SmiNode * smiNodePtr)1643 int smiGetNodeLine(SmiNode *smiNodePtr)
1644 {
1645     return ((Object *)smiNodePtr)->line;
1646 }
1647 
1648 
1649 
smiGetFirstElement(SmiNode * smiNodePtr)1650 SmiElement *smiGetFirstElement(SmiNode *smiNodePtr)
1651 {
1652     List	      *listPtr;
1653 
1654     if (!smiNodePtr) {
1655 	return NULL;
1656     }
1657 
1658     listPtr = ((Object *)smiNodePtr)->listPtr;
1659 
1660     return (SmiElement *)listPtr;
1661 }
1662 
1663 
1664 
smiGetNextElement(SmiElement * smiElementPtr)1665 SmiElement *smiGetNextElement(SmiElement *smiElementPtr)
1666 {
1667     List	      *listPtr;
1668 
1669     if (!smiElementPtr) {
1670 	return NULL;
1671     }
1672 
1673     listPtr = ((List *)smiElementPtr)->nextPtr;
1674 
1675     return (SmiElement *)listPtr;
1676 }
1677 
1678 
1679 
smiGetElementNode(SmiElement * smiElementPtr)1680 SmiNode *smiGetElementNode(SmiElement *smiElementPtr)
1681 {
1682     if ((Object *)((List *)smiElementPtr)->ptr)
1683         return &((Object *)((List *)smiElementPtr)->ptr)->export;
1684     else
1685         return NULL;
1686 }
1687 
1688 
1689 
smiGetFirstOption(SmiNode * smiComplianceNodePtr)1690 SmiOption *smiGetFirstOption(SmiNode *smiComplianceNodePtr)
1691 {
1692     Object	      *objectPtr;
1693 
1694     if (!smiComplianceNodePtr) {
1695 	return NULL;
1696     }
1697 
1698     objectPtr = (Object *)smiComplianceNodePtr;
1699 
1700     if (!objectPtr->optionlistPtr) {
1701 	return NULL;
1702     }
1703 
1704     if (objectPtr->export.nodekind != SMI_NODEKIND_COMPLIANCE) {
1705 	return NULL;
1706     }
1707 
1708     return &((Option *)objectPtr->optionlistPtr->ptr)->export;
1709 }
1710 
1711 
1712 
smiGetNextOption(SmiOption * smiOptionPtr)1713 SmiOption *smiGetNextOption(SmiOption *smiOptionPtr)
1714 {
1715     List	      *listPtr;
1716 
1717     if (!smiOptionPtr) {
1718 	return NULL;
1719     }
1720 
1721     for (listPtr =
1722 	    ((Option *)smiOptionPtr)->compliancePtr->optionlistPtr;
1723 	 listPtr;
1724 	 listPtr = listPtr->nextPtr) {
1725 	if ((Option *)(listPtr->ptr) == (Option *)smiOptionPtr) {
1726 	    if (listPtr->nextPtr) {
1727 		return &((Option *)listPtr->nextPtr->ptr)->export;
1728 	    } else {
1729 		return NULL;
1730 	    }
1731 	}
1732     }
1733 
1734     return NULL;
1735 }
1736 
1737 
1738 
smiGetOptionNode(SmiOption * smiOptionPtr)1739 SmiNode *smiGetOptionNode(SmiOption *smiOptionPtr)
1740 {
1741     return &((Option *)smiOptionPtr)->objectPtr->export;
1742 }
1743 
1744 
1745 
smiGetOptionLine(SmiOption * smiOptionPtr)1746 int smiGetOptionLine(SmiOption *smiOptionPtr)
1747 {
1748     return ((Option *)smiOptionPtr)->line;
1749 }
1750 
1751 
1752 
smiGetFirstRefinement(SmiNode * smiComplianceNodePtr)1753 SmiRefinement *smiGetFirstRefinement(SmiNode *smiComplianceNodePtr)
1754 {
1755     Object	      *objectPtr;
1756 
1757     if (!smiComplianceNodePtr) {
1758 	return NULL;
1759     }
1760 
1761     objectPtr = (Object *)smiComplianceNodePtr;
1762 
1763     if (!objectPtr->refinementlistPtr) {
1764 	return NULL;
1765     }
1766 
1767     if (objectPtr->export.nodekind != SMI_NODEKIND_COMPLIANCE) {
1768 	return NULL;
1769     }
1770 
1771     return &((Refinement *)objectPtr->refinementlistPtr->ptr)->export;
1772 }
1773 
1774 
1775 
smiGetNextRefinement(SmiRefinement * smiRefinementPtr)1776 SmiRefinement *smiGetNextRefinement(SmiRefinement *smiRefinementPtr)
1777 {
1778     List	      *listPtr;
1779 
1780     if (!smiRefinementPtr) {
1781 	return NULL;
1782     }
1783 
1784     for (listPtr =
1785 	    ((Refinement *)smiRefinementPtr)->compliancePtr->refinementlistPtr;
1786 	 listPtr;
1787 	 listPtr = listPtr->nextPtr) {
1788 	if ((Refinement *)(listPtr->ptr) == (Refinement *)smiRefinementPtr) {
1789 	    if (listPtr->nextPtr) {
1790 		return &((Refinement *)listPtr->nextPtr->ptr)->export;
1791 	    } else {
1792 		return NULL;
1793 	    }
1794 	}
1795     }
1796 
1797     return NULL;
1798 }
1799 
1800 
1801 
smiGetRefinementNode(SmiRefinement * smiRefinementPtr)1802 SmiNode *smiGetRefinementNode(SmiRefinement *smiRefinementPtr)
1803 {
1804     return &((Refinement *)smiRefinementPtr)->objectPtr->export;
1805 }
1806 
1807 
1808 
smiGetRefinementType(SmiRefinement * smiRefinementPtr)1809 SmiType *smiGetRefinementType(SmiRefinement *smiRefinementPtr)
1810 {
1811     Type *typePtr;
1812 
1813     typePtr = ((Refinement *)smiRefinementPtr)->typePtr;
1814 
1815     if (!typePtr ||
1816 	typePtr->export.basetype == SMI_BASETYPE_UNKNOWN) {
1817 	return NULL;
1818     }
1819 
1820     return &typePtr->export;
1821 }
1822 
1823 
1824 
smiGetRefinementWriteType(SmiRefinement * smiRefinementPtr)1825 SmiType *smiGetRefinementWriteType(SmiRefinement *smiRefinementPtr)
1826 {
1827     Type *typePtr;
1828 
1829     typePtr = ((Refinement *)smiRefinementPtr)->writetypePtr;
1830 
1831     if (!typePtr ||
1832 	typePtr->export.basetype == SMI_BASETYPE_UNKNOWN) {
1833 	return NULL;
1834     }
1835 
1836     return &typePtr->export;
1837 }
1838 
1839 
1840 
smiGetRefinementLine(SmiRefinement * smiRefinementPtr)1841 int smiGetRefinementLine(SmiRefinement *smiRefinementPtr)
1842 {
1843     return ((Refinement *)smiRefinementPtr)->line;
1844 }
1845 
1846 
1847 
smiGetFirstUniquenessElement(SmiNode * smiNodePtr)1848 SmiElement *smiGetFirstUniquenessElement(SmiNode *smiNodePtr)
1849 {
1850     List	      *listPtr;
1851 
1852     if (!smiNodePtr) {
1853 	return NULL;
1854     }
1855 
1856     listPtr = ((Object *)smiNodePtr)->uniquenessPtr;
1857 
1858     return (SmiElement *)listPtr;
1859 }
1860 
1861 
1862 
smiRenderOID(unsigned int oidlen,SmiSubid * oid,int flags)1863 char *smiRenderOID(unsigned int oidlen, SmiSubid *oid, int flags)
1864 {
1865     SmiNode *nodePtr = NULL;
1866     SmiModule *modulePtr = NULL;
1867     unsigned int i = 0;
1868     char *ss, *s = NULL;
1869 
1870     if (!oid) {
1871 	if (flags & SMI_RENDER_UNKNOWN) {
1872 	    smiAsprintf(&s, SMI_UNKNOWN_LABEL);
1873 	} else {
1874 	    s = NULL;
1875 	}
1876 	return s;
1877     }
1878 
1879     if (flags & (SMI_RENDER_NAME | SMI_RENDER_QUALIFIED)) {
1880 	int len;
1881 	for (len = oidlen; len; len--) {
1882 	    nodePtr = smiGetNodeByOID(len, oid);
1883 	    if (! nodePtr || nodePtr->name) break;
1884 	}
1885 	if (nodePtr && nodePtr->name) {
1886 	    i = nodePtr->oidlen;
1887 	    if (flags & SMI_RENDER_QUALIFIED) {
1888 		modulePtr = smiGetNodeModule(nodePtr);
1889 	    }
1890 	    if (modulePtr) {
1891 		smiAsprintf(&s, "%s::%s",
1892 			    modulePtr->name, nodePtr->name);
1893 	    } else {
1894 		smiAsprintf(&s, "%s", nodePtr->name);
1895 	    }
1896 	}
1897     }
1898 
1899     for (; i < oidlen; i++) {
1900 	ss = s;
1901 	smiAsprintf(&s, "%s%s%u", ss ? ss : "", i ? "." : "", oid[i]);
1902 	smiFree(ss);
1903     }
1904 
1905     if ((!s) && (flags & SMI_RENDER_UNKNOWN)) {
1906 	smiAsprintf(&s, SMI_UNKNOWN_LABEL);
1907     }
1908 
1909     return s;
1910 }
1911 
1912 
1913 
smiRenderValue(SmiValue * smiValuePtr,SmiType * smiTypePtr,int flags)1914 char *smiRenderValue(SmiValue *smiValuePtr, SmiType *smiTypePtr, int flags)
1915 {
1916     unsigned int i, pfx;
1917     int j, k, n, have_pfx;
1918     char *last_fmt, *fmt;
1919     SmiUnsigned64 vv;
1920     int xlen;
1921     SmiNamedNumber *nn;
1922     char *s, *ss;
1923     char f[8];
1924     SmiUnsigned32 v32;
1925     SmiUnsigned64 v64;
1926 
1927     if (!smiValuePtr) {
1928 	if (flags & SMI_RENDER_UNKNOWN) {
1929 	    smiAsprintf(&s, SMI_UNKNOWN_LABEL);
1930 	} else {
1931 	    s = NULL;
1932 	}
1933 	return s;
1934     }
1935 
1936     switch (smiValuePtr->basetype) {
1937     case SMI_BASETYPE_UNSIGNED32:
1938 	if (!(flags & SMI_RENDER_FORMAT) ||
1939 	    !smiTypePtr || !smiTypePtr->format ||
1940 	    !strlen(smiTypePtr->format) || smiTypePtr->format[0] == 'd') {
1941 	    if (smiTypePtr->format && (strlen(smiTypePtr->format) >= 3) &&
1942 		(smiTypePtr->format[1] == '-')) {
1943 		i = atoi(&smiTypePtr->format[2]);
1944 		if (i < 0) i = 0;
1945 		if (i > 20) i = 20;
1946 		smiAsprintf(&s, "%0*lu.",
1947 			    1 + i,
1948 			    smiValuePtr->value.unsigned32);
1949 		if (s) {
1950 		    for (j = strlen(s) - 1; i > 0; i--, j--) {
1951 			s[j] = s[j-1];
1952 		    }
1953 		    s[j] = '.';
1954 		}
1955 	    } else {
1956 		smiAsprintf(&s, "%lu", smiValuePtr->value.unsigned32);
1957 	    }
1958 	} else if (smiTypePtr->format[0] == 'x') {
1959 	    smiAsprintf(&s, "%lx", smiValuePtr->value.unsigned32);
1960 	} else if (smiTypePtr->format[0] == 'o') {
1961 	    smiAsprintf(&s, "%lo", smiValuePtr->value.unsigned32);
1962 	} else if (smiTypePtr->format[0] == 'b') {
1963 	    for (i = 32 - 1;
1964 		 i > 0 && !(smiValuePtr->value.unsigned32 & (1 << i)); i--);
1965 	    s = smiMalloc(i + 1 + 1);
1966 	    if (s) {
1967 		for (j = 0; i >= 0; i--, j++) {
1968 		    s[j] = smiValuePtr->value.unsigned32 & (1<<i) ? '1' : '0';
1969 		}
1970 		s[j] = 0;
1971 	    }
1972 	}
1973 	break;
1974     case SMI_BASETYPE_UNSIGNED64:
1975 	if (!(flags & SMI_RENDER_FORMAT) ||
1976 	    !smiTypePtr || !smiTypePtr->format ||
1977 	    !strlen(smiTypePtr->format) || smiTypePtr->format[0] == 'd') {
1978 	    if (smiTypePtr->format && (strlen(smiTypePtr->format) >= 3) &&
1979 		(smiTypePtr->format[1] == '-')) {
1980 		i = atoi(&smiTypePtr->format[2]);
1981 		if (i < 0) i = 0;
1982 		if (i > 20) i = 20;
1983 		sprintf(f, "%%0%s.", UINT64_FORMAT);
1984 		f[2] = '*';
1985 		smiAsprintf(&s, f,
1986 			    1 + i,
1987 			    smiValuePtr->value.unsigned64);
1988 		if (s) {
1989 		    for (j = strlen(s) - 1; i > 0; i--, j--) {
1990 			s[j] = s[j-1];
1991 		    }
1992 		    s[j] = '.';
1993 		}
1994 	    } else {
1995 		smiAsprintf(&s, UINT64_FORMAT, smiValuePtr->value.unsigned64);
1996 	    }
1997 	} else if (smiTypePtr->format[0] == 'x') {
1998 	    strcpy(f, UINT64_FORMAT);
1999 	    f[strlen(f)-1] = 'x';
2000 	    smiAsprintf(&s, f, smiValuePtr->value.unsigned64);
2001 	} else if (smiTypePtr->format[0] == 'o') {
2002 	    strcpy(f, UINT64_FORMAT);
2003 	    f[strlen(f)-1] = 'o';
2004 	    smiAsprintf(&s, f, smiValuePtr->value.unsigned64);
2005 	} else if (smiTypePtr->format[0] == 'b') {
2006 	    for (i = 64 - 1;
2007 		 i > 0 && !(smiValuePtr->value.unsigned64 & (1 << i)); i--);
2008 	    s = smiMalloc(i + 1 + 1);
2009 	    if (s) {
2010 		for (j = 0; i >= 0; i--, j++) {
2011 		    s[j] = smiValuePtr->value.unsigned64 & (1<<i) ? '1' : '0';
2012 		}
2013 		s[j] = 0;
2014 	    }
2015 	}
2016 	break;
2017     case SMI_BASETYPE_INTEGER32:
2018 	if (!(flags & SMI_RENDER_FORMAT) ||
2019 	    !smiTypePtr || !smiTypePtr->format ||
2020 	    !strlen(smiTypePtr->format) || smiTypePtr->format[0] == 'd') {
2021 	    if (smiTypePtr->format && (strlen(smiTypePtr->format) >= 3) &&
2022 		(smiTypePtr->format[1] == '-')) {
2023 		i = atoi(&smiTypePtr->format[2]);
2024 		if (i < 0) i = 0;
2025 		if (i > 20) i = 20;
2026 		smiAsprintf(&s, "%0*ld.",
2027 			    1 + i + (smiValuePtr->value.integer32 < 0 ? 1 : 0),
2028 			    smiValuePtr->value.integer32);
2029 		if (s) {
2030 		    for (j = strlen(s) - 1; i > 0; i--, j--) {
2031 			s[j] = s[j-1];
2032 		    }
2033 		    s[j] = '.';
2034 		}
2035 	    } else {
2036 		smiAsprintf(&s, "%ld", smiValuePtr->value.integer32);
2037 	    }
2038 	} else if (smiTypePtr->format[0] == 'x') {
2039 	    if (smiValuePtr->value.integer32 >= 0) {
2040 		smiAsprintf(&s, "%lx", smiValuePtr->value.integer32);
2041 	    } else {
2042 		smiAsprintf(&s, "-%lx", - smiValuePtr->value.integer32);
2043 	    }
2044 	} else if (smiTypePtr->format[0] == 'o') {
2045 	    if (smiValuePtr->value.integer32 >= 0) {
2046 		smiAsprintf(&s, "%lo", smiValuePtr->value.integer32);
2047 	    } else {
2048 		smiAsprintf(&s, "-%lo", - smiValuePtr->value.integer32);
2049 	    }
2050 	} else if (smiTypePtr->format[0] == 'b') {
2051 	    if (smiValuePtr->value.integer32 >= 0) {
2052 		v32 = smiValuePtr->value.integer32;
2053 		j = 0;
2054 	    } else {
2055 		v32 = - smiValuePtr->value.integer32;
2056 		j = 1;
2057 	    }
2058 	    for (i = 32 - 1;
2059 		 i > 0 && !(v32 & (1 << i)); i--);
2060 	    s = smiMalloc(i + j + 1 + 1);
2061 	    if (s) {
2062 		s[0] = '-';
2063 		for (; i >= 0; i--, j++) {
2064 		    s[j] = v32 & (1<<i) ? '1' : '0';
2065 		}
2066 		s[j] = 0;
2067 	    }
2068 	}
2069 	break;
2070     case SMI_BASETYPE_INTEGER64:
2071 	if (!(flags & SMI_RENDER_FORMAT) ||
2072 	    !smiTypePtr || !smiTypePtr->format ||
2073 	    !strlen(smiTypePtr->format) || smiTypePtr->format[0] == 'd') {
2074 	    if (smiTypePtr->format && (strlen(smiTypePtr->format) >= 3) &&
2075 		(smiTypePtr->format[1] == '-')) {
2076 		i = atoi(&smiTypePtr->format[2]);
2077 		if (i < 0) i = 0;
2078 		if (i > 20) i = 20;
2079 		sprintf(f, "%%0%s.", INT64_FORMAT);
2080 		f[2] = '*';
2081 		smiAsprintf(&s, f,
2082 			    1 + i + (smiValuePtr->value.integer64 < 0 ? 1 : 0),
2083 			    smiValuePtr->value.integer64);
2084 		if (s) {
2085 		    for (j = strlen(s) - 1; i > 0; i--, j--) {
2086 			s[j] = s[j-1];
2087 		    }
2088 		    s[j] = '.';
2089 		}
2090 	    } else {
2091 		smiAsprintf(&s, INT64_FORMAT, smiValuePtr->value.integer64);
2092 	    }
2093 	} else if (smiTypePtr->format[0] == 'x') {
2094 	    if (smiValuePtr->value.integer64 >= 0) {
2095 		strcpy(f, UINT64_FORMAT);
2096 		f[strlen(f)-1] = 'x';
2097 		smiAsprintf(&s, f, smiValuePtr->value.integer64);
2098 	    } else {
2099 		sprintf(f, "-%s", UINT64_FORMAT);
2100 		f[strlen(f)-1] = 'x';
2101 		smiAsprintf(&s, f, - smiValuePtr->value.integer64);
2102 	    }
2103 	} else if (smiTypePtr->format[0] == 'o') {
2104 	    if (smiValuePtr->value.integer64 >= 0) {
2105 		strcpy(f, UINT64_FORMAT);
2106 		sprintf(f, "-%s", UINT64_FORMAT);
2107 		f[strlen(f)-1] = 'o';
2108 		smiAsprintf(&s, f, smiValuePtr->value.integer64);
2109 	    } else {
2110 		smiAsprintf(&s, f, - smiValuePtr->value.integer64);
2111 	    }
2112 	} else if (smiTypePtr->format[0] == 'b') {
2113 	    if (smiValuePtr->value.integer64 >= 0) {
2114 		v64 = smiValuePtr->value.integer64;
2115 		j = 0;
2116 	    } else {
2117 		v64 = - smiValuePtr->value.integer64;
2118 		j = 1;
2119 	    }
2120 	    for (i = 64 - 1;
2121 		 i > 0 && !(v64 & (1 << i)); i--);
2122 	    s = smiMalloc(i + j + 1 + 1);
2123 	    if (s) {
2124 		s[0] = '-';
2125 		for (; i >= 0; i--, j++) {
2126 		    s[j] = v64 & (1<<i) ? '1' : '0';
2127 		}
2128 		s[j] = 0;
2129 	    }
2130 	}
2131 	break;
2132     case SMI_BASETYPE_OBJECTIDENTIFIER:
2133 	s = smiRenderOID(smiValuePtr->len, smiValuePtr->value.oid, flags);
2134 	break;
2135     case SMI_BASETYPE_OCTETSTRING:
2136 	if (!(flags & SMI_RENDER_FORMAT) ||
2137 	    (!smiTypePtr->format &&
2138 	     (smiTypePtr->name && strcmp( smiTypePtr->name, "IpAddress")) ) ) {
2139 	    for (i = 0; i < smiValuePtr->len; i++) {
2140 		if (!isprint((int)smiValuePtr->value.ptr[i])) break;
2141 	    }
2142 	    if ((i < smiValuePtr->len) ||
2143 		!(flags & SMI_RENDER_PRINTABLE)) {
2144 		smiAsprintf(&s, "");
2145 		for (i=0; i < smiValuePtr->len; i++) {
2146 		    ss = s;
2147 		    smiAsprintf(&s, "%s%02x", ss, smiValuePtr->value.ptr[i]);
2148 		    smiFree(ss);
2149 		}
2150 	    } else {
2151 		smiAsprintf(&s, "%s", smiValuePtr->value.ptr);
2152 	    }
2153 	} else {
2154 	    i = 0;
2155 	    smiAsprintf(&s, "");
2156 	    /* SNMPv2-SMI:IpAddress does not have a display hint.
2157 	       ==> let's use this one: "1d." if we have an IpAddress here */
2158 	    fmt = (smiTypePtr->name &&
2159 		   strcmp( smiTypePtr->name, "IpAddress" ) ) ?
2160 		smiTypePtr->format : "1d.";
2161 	    while (*fmt && i < smiValuePtr->len) {
2162 		last_fmt = fmt;
2163 		have_pfx = pfx = 0; /* scan prefix: */
2164 		while (*fmt && isdigit((int)*fmt)) {
2165 		    pfx = pfx * 10 + *fmt - '0', have_pfx = 1, fmt++;
2166 		}
2167 		if (! have_pfx) {
2168 		    pfx = 1;
2169 		}
2170 		switch (*fmt) {
2171 		case 't':
2172 		    /* XXX UTF-8 not implemented, fall through to ASCII (a) */
2173 		case 'a':
2174 		    n = (pfx < (smiValuePtr->len - i)) ?
2175 			pfx : smiValuePtr->len - i;
2176 		    for (k = 0; k < n; k++) {
2177 			if (! isascii((int) smiValuePtr->value.ptr[i+k])) {
2178 			    smiFree(s);
2179 			    if (flags & SMI_RENDER_UNKNOWN) {
2180 				smiAsprintf(&s, SMI_UNKNOWN_LABEL);
2181 			    } else {
2182 				s = NULL;
2183 			    }
2184 			    return s;
2185 			}
2186 			ss = s;
2187 			smiAsprintf(&s, "%s%c", ss, smiValuePtr->value.ptr[i+k]);
2188 			smiFree(ss);
2189 		    }
2190 		    i += n;
2191 		    break;
2192 		case 'b':
2193 		case 'd':
2194 		case 'o':
2195 		case 'x':
2196 		    /* XXX: limited to no more than
2197 		       sizeof(SmiUnsigned64) octets */
2198 		    vv = 0;
2199 		    xlen = pfx * 2;
2200 		    while (pfx > 0 && i < smiValuePtr->len) {
2201 			vv = vv * 256 +
2202 			     ((unsigned char)smiValuePtr->value.ptr[i]);
2203 			i++;
2204 			pfx--;
2205 		    }
2206 		    switch (*fmt) {
2207 		    case 'd':
2208 			ss = s;
2209 			sprintf(f, "%%s%s", UINT64_FORMAT);
2210 			smiAsprintf(&s, f, ss, vv);
2211 			smiFree(ss);
2212 			break;
2213 		    case 'o':
2214 			ss = s;
2215 			sprintf(f, "%%s%s", UINT64_FORMAT);
2216 			f[strlen(f)-1] = 'o';
2217 			smiAsprintf(&s, f, ss, vv);
2218 			smiFree(ss);
2219 			break;
2220 		    case 'x':
2221 			ss = s;
2222 			sprintf(f, "%%s%%0%s", UINT64_FORMAT);
2223 			f[4] = '*';
2224 			f[strlen(f)-1] = 'x';
2225 			smiAsprintf(&s, f, ss, xlen, vv);
2226 			smiFree(ss);
2227 			break;
2228 		    case 'b':
2229 			k = pfx * 8 - 1;
2230 			if (k > sizeof(SmiUnsigned64) * 8 - 1)
2231 			    k = sizeof(SmiUnsigned64) * 8 - 1;
2232 			for (j = 0; k >= 0; k--, j++) {
2233 			    ss = s;
2234 			    smiAsprintf(&s, "%s%c",
2235 					ss, vv & (1 << k) ? '1' : '0');
2236 			    smiFree(ss);
2237 			}
2238 			break;
2239 		    }
2240 		    break;
2241 		default:
2242 		    smiFree(s);
2243 		    if (flags & SMI_RENDER_UNKNOWN) {
2244 			smiAsprintf(&s, SMI_UNKNOWN_LABEL);
2245 		    } else {
2246 			s = NULL;
2247 		    }
2248 		    return s;
2249 		}
2250 		fmt++;
2251 
2252 		/*
2253 		 * Check for a separator and repeat with last format if
2254 		 * data is still available.
2255 		 */
2256 		if (*fmt && ! isdigit((int) *fmt) && *fmt != '*') {
2257 		    if (i < smiValuePtr->len) {
2258 			ss = s;
2259 			smiAsprintf(&s, "%s%c", ss, fmt[0]);
2260 			smiFree(ss);
2261 		    }
2262 		    fmt++;
2263 		}
2264 
2265 		if (! *fmt && (i < smiValuePtr->len)) {
2266 		    fmt = last_fmt;
2267 		}
2268 	    }
2269 	}
2270 	break;
2271     case SMI_BASETYPE_ENUM:
2272 	if ((flags & SMI_RENDER_NAME) && (smiTypePtr)) {
2273 	    for (nn = smiGetFirstNamedNumber(smiTypePtr); nn;
2274 		 nn = smiGetNextNamedNumber(nn)) {
2275 		if (nn->value.value.integer32 == smiValuePtr->value.integer32)
2276 		    break;
2277 	    }
2278 	    if (nn) {
2279 		if (flags & SMI_RENDER_NUMERIC) {
2280 		    smiAsprintf(&s, "%s(%ld)",
2281 				nn->name, nn->value.value.integer32);
2282 		} else {
2283 		    smiAsprintf(&s, "%s", nn->name);
2284 		}
2285 	    } else {
2286 		smiAsprintf(&s, "%ld", smiValuePtr->value.integer32);
2287 	    }
2288 	} else {
2289 	    smiAsprintf(&s, "%ld", smiValuePtr->value.integer32);
2290 	}
2291 	break;
2292     case SMI_BASETYPE_BITS:
2293 	smiAsprintf(&s, "");
2294 	for (i = 0, nn = NULL; i < smiValuePtr->len * 8; i++) {
2295 	    if (smiValuePtr->value.ptr[i/8] & (1 << (7-(i%8)))) {
2296 		if ((flags & SMI_RENDER_NAME) && (smiTypePtr)) {
2297 		    for (nn = smiGetFirstNamedNumber(smiTypePtr); nn;
2298 			 nn = smiGetNextNamedNumber(nn)) {
2299 			if (nn->value.value.unsigned32 == i)
2300 			    break;
2301 		    }
2302 		}
2303 		ss = s;
2304 		if ((flags & SMI_RENDER_NAME) &&
2305 		    (flags & SMI_RENDER_NUMERIC) && nn) {
2306 		    smiAsprintf(&s, "%s%s%s(%d)",
2307 				ss, strlen(ss) ? " " : "", nn->name, i);
2308 		} else if (nn) {
2309 		    smiAsprintf(&s, "%s%s%s",
2310 				ss, strlen(ss) ? " " : "", nn->name);
2311 		} else {
2312 		    smiAsprintf(&s, "%s%s%d",
2313 				ss, strlen(ss) ? " " : "", i);
2314 		}
2315 		smiFree(ss);
2316 	    }
2317 	}
2318 	break;
2319     case SMI_BASETYPE_FLOAT32:
2320     case SMI_BASETYPE_FLOAT64:
2321     case SMI_BASETYPE_FLOAT128:
2322     case SMI_BASETYPE_UNKNOWN:
2323     default:
2324 	if (flags & SMI_RENDER_UNKNOWN) {
2325 	    smiAsprintf(&s, SMI_UNKNOWN_LABEL);
2326 	} else {
2327 	    s = NULL;
2328 	}
2329 	break;
2330     }
2331 
2332     return s;
2333 }
2334 
smiRenderNode(SmiNode * smiNodePtr,int flags)2335 char *smiRenderNode(SmiNode *smiNodePtr, int flags)
2336 {
2337     char *s;
2338     SmiModule *modulePtr;
2339 
2340     if ((!smiNodePtr) || (smiNodePtr->name == NULL)) {
2341 	if (flags & SMI_RENDER_UNKNOWN) {
2342 	    smiAsprintf(&s, SMI_UNKNOWN_LABEL);
2343 	} else {
2344 	    s = NULL;
2345 	}
2346     } else {
2347 	modulePtr = smiGetNodeModule(smiNodePtr);
2348 	if ((!(flags & SMI_RENDER_QUALIFIED)) ||
2349 	    (!modulePtr) ||
2350 	    (!strlen(modulePtr->name))) {
2351 	    smiAsprintf(&s, "%s", smiNodePtr->name);
2352 	} else {
2353 	    smiAsprintf(&s, "%s::%s", modulePtr->name, smiNodePtr->name);
2354 	}
2355     }
2356     return s;
2357 }
2358 
2359 
2360 
smiRenderType(SmiType * smiTypePtr,int flags)2361 char *smiRenderType(SmiType *smiTypePtr, int flags)
2362 {
2363     char *s;
2364     SmiModule *modulePtr;
2365 
2366     if ((!smiTypePtr) || (smiTypePtr->name == NULL)) {
2367 	if (flags & SMI_RENDER_UNKNOWN) {
2368 	    smiAsprintf(&s, SMI_UNKNOWN_LABEL);
2369 	} else {
2370 	    s = NULL;
2371 	}
2372     } else {
2373 	modulePtr = smiGetTypeModule(smiTypePtr);
2374 	if ((!(flags & SMI_RENDER_QUALIFIED)) ||
2375 	    (!modulePtr) ||
2376 	    (!strlen(modulePtr->name))) {
2377 	    smiAsprintf(&s, "%s", smiTypePtr->name);
2378 	} else {
2379 	    smiAsprintf(&s, "%s::%s", modulePtr->name, smiTypePtr->name);
2380 	}
2381     }
2382     return s;
2383 }
2384 
2385 
2386 
smiGetMinSize(SmiType * smiType)2387 unsigned int smiGetMinSize(SmiType *smiType)
2388 {
2389     SmiRange *smiRange;
2390     SmiType  *parentType;
2391     unsigned int min = 65535, size;
2392 
2393     switch (smiType->basetype) {
2394     case SMI_BASETYPE_BITS:
2395 	return 0;
2396     case SMI_BASETYPE_OCTETSTRING:
2397     case SMI_BASETYPE_OBJECTIDENTIFIER:
2398 	size = 0;
2399 	break;
2400     default:
2401 	return 0;
2402     }
2403 
2404     for (smiRange = smiGetFirstRange(smiType);
2405 	 smiRange ; smiRange = smiGetNextRange(smiRange)) {
2406 	if (smiRange->minValue.value.unsigned32 < min) {
2407 	    min = smiRange->minValue.value.unsigned32;
2408 	}
2409     }
2410     if (min < 65535 && min > size) {
2411 	size = min;
2412     }
2413 
2414     parentType = smiGetParentType(smiType);
2415     if (parentType) {
2416 	unsigned int psize = smiGetMinSize(parentType);
2417 	if (psize > size) {
2418 	    size = psize;
2419 	}
2420     }
2421 
2422     return size;
2423 }
2424 
2425 
2426 
smiGetMaxSize(SmiType * smiType)2427 unsigned int smiGetMaxSize(SmiType *smiType)
2428 {
2429     SmiRange *smiRange;
2430     SmiType  *parentType;
2431     SmiNamedNumber *nn;
2432     unsigned int max = 0, size;
2433 
2434     switch (smiType->basetype) {
2435     case SMI_BASETYPE_BITS:
2436     case SMI_BASETYPE_OCTETSTRING:
2437 	size = 65535;
2438 	break;
2439     case SMI_BASETYPE_OBJECTIDENTIFIER:
2440 	size = 128;
2441 	break;
2442     default:
2443 	return 0xffffffff;
2444     }
2445 
2446     if (smiType->basetype == SMI_BASETYPE_BITS) {
2447 	for (nn = smiGetFirstNamedNumber(smiType);
2448 	     nn;
2449 	     nn = smiGetNextNamedNumber(nn)) {
2450 	    if (nn->value.value.unsigned32 > max) {
2451 		max = nn->value.value.unsigned32;
2452 	    }
2453 	}
2454 	size = (max / 8) + 1;
2455 	return size;
2456     }
2457 
2458     for (smiRange = smiGetFirstRange(smiType);
2459 	 smiRange ; smiRange = smiGetNextRange(smiRange)) {
2460 	if (smiRange->maxValue.value.unsigned32 > max) {
2461 	    max = smiRange->maxValue.value.unsigned32;
2462 	}
2463     }
2464     if (max > 0 && max < size) {
2465 	size = max;
2466     }
2467 
2468     parentType = smiGetParentType(smiType);
2469     if (parentType) {
2470 	unsigned int psize = smiGetMaxSize(parentType);
2471 	if (psize < size) {
2472 	    size = psize;
2473 	}
2474     }
2475 
2476     return size;
2477 }
2478 
2479 
2480 
smiUnpack(SmiNode * row,SmiSubid * oid,unsigned int oidlen,SmiValue ** vals,int * valslen)2481 int smiUnpack(SmiNode *row, SmiSubid *oid, unsigned int oidlen,
2482 	      SmiValue **vals, int *valslen)
2483 {
2484     SmiNode *indexNode = NULL;
2485     SmiElement *smiElement;
2486     SmiNode *iNode;
2487     SmiType *iType;
2488     int i, j, last = 0;
2489 
2490     if (!vals || !valslen || !row || !oid) {
2491 	return 0;
2492     }
2493 
2494     switch (row->indexkind) {
2495     case SMI_INDEX_INDEX:
2496     case SMI_INDEX_REORDER:
2497 	indexNode = row;
2498 	break;
2499     case SMI_INDEX_EXPAND:	/* TODO: we have to do more work here! */
2500 	indexNode = NULL;
2501 	break;
2502     case SMI_INDEX_AUGMENT:
2503     case SMI_INDEX_SPARSE:
2504 	indexNode = smiGetRelatedNode(row);
2505 	break;
2506     case SMI_INDEX_UNKNOWN:
2507 	indexNode = NULL;
2508 	break;
2509     }
2510 
2511     *valslen = 0;
2512     for (smiElement = smiGetFirstElement(indexNode);
2513 	 smiElement; smiElement = smiGetNextElement(smiElement)) {
2514 	iNode = smiGetElementNode(smiElement);
2515 	if (iNode) {
2516 	    iType = smiGetNodeType(iNode);
2517 	    if (! iType) break;
2518 	    (*valslen)++;
2519 	}
2520     }
2521     if (smiElement) {
2522 	return 0;
2523     }
2524 
2525     *vals = smiMalloc(*valslen * sizeof(SmiValue));
2526 
2527     for (smiElement = smiGetFirstElement(indexNode), i = 0, j = 0;
2528 	 smiElement; smiElement = smiGetNextElement(smiElement), i++) {
2529 	iNode = smiGetElementNode(smiElement);
2530 	last = (smiGetNextElement(smiElement) == NULL);
2531 	iType = smiGetNodeType(iNode);
2532 	fprintf(stderr, "** %s (%s)\n", iNode->name, iType->name);
2533 	(*vals)[i].basetype = iType->basetype;
2534 	switch (iType->basetype) {
2535 	case SMI_BASETYPE_ENUM:
2536 	case SMI_BASETYPE_INTEGER32:
2537 	    (*vals)[i].value.integer32 = oid[j]; j++;
2538 	    break;
2539 	case SMI_BASETYPE_UNSIGNED32:
2540 	    (*vals)[i].value.unsigned32 = oid[j]; j++;
2541 	    break;
2542 	case SMI_BASETYPE_OCTETSTRING:
2543 	    /* need to know whether implied/fixed length or not */
2544 	    break;
2545 	case SMI_BASETYPE_OBJECTIDENTIFIER:
2546 	    /* need to know whether implied/fixed length or not */
2547 	    break;
2548 	default:
2549 	    return 0;
2550 	}
2551     }
2552 
2553     return *valslen;
2554 }
2555 
2556 
2557 
smiAsprintf(char ** strp,const char * format,...)2558 int smiAsprintf(char **strp, const char *format, ...)
2559 {
2560     int rc;
2561     va_list ap;
2562 
2563     va_start(ap, format);
2564     rc = vasprintf(strp, format, ap);
2565     va_end(ap);
2566     if (! strp) {
2567 	smiPrintError(NULL, ERR_OUT_OF_MEMORY);
2568     }
2569     return rc;
2570 }
2571 
2572 
2573 
smiVasprintf(char ** strp,const char * format,va_list ap)2574 int smiVasprintf(char **strp, const char *format, va_list ap)
2575 {
2576     int rc;
2577 
2578     rc = vasprintf(strp, format, ap);
2579     if (! strp) {
2580 	smiPrintError(NULL, ERR_OUT_OF_MEMORY);
2581     }
2582     return rc;
2583 }
2584 
2585 
smiGetMinMaxRange(SmiType * smiType,SmiValue * min,SmiValue * max)2586 int smiGetMinMaxRange(SmiType *smiType, SmiValue *min, SmiValue *max)
2587 {
2588     SmiBasetype    basetype = SMI_BASETYPE_UNKNOWN;
2589     SmiRange       *range;
2590 
2591     min->basetype = max->basetype = SMI_BASETYPE_UNKNOWN;
2592     min->len = max->len = 0;
2593 
2594     range = smiGetFirstRange(smiType);
2595     if (!range) {
2596 	return 0;
2597     }
2598 
2599     basetype = range->minValue.basetype;
2600     min->basetype = max->basetype = basetype;
2601 
2602     switch (basetype) {
2603     case SMI_BASETYPE_INTEGER32:
2604 	min->value.integer32 = SMI_BASETYPE_INTEGER32_MAX;
2605 	max->value.integer32 = SMI_BASETYPE_INTEGER32_MIN;
2606 	break;
2607     case SMI_BASETYPE_INTEGER64:
2608 	min->value.integer64 = SMI_BASETYPE_INTEGER64_MAX;
2609 	max->value.integer64 = SMI_BASETYPE_INTEGER64_MIN;
2610 	break;
2611     case SMI_BASETYPE_UNSIGNED32:
2612 	min->value.unsigned32 = SMI_BASETYPE_UNSIGNED32_MAX;
2613 	max->value.unsigned32 = SMI_BASETYPE_UNSIGNED32_MIN;
2614 	break;
2615     case SMI_BASETYPE_UNSIGNED64:
2616 	min->value.unsigned64 = SMI_BASETYPE_UNSIGNED64_MAX;
2617 	max->value.unsigned64 = SMI_BASETYPE_UNSIGNED32_MIN;
2618 	break;
2619     default:
2620 	fprintf(stderr, "smidump: unexpected basetype %d\n", basetype);
2621 	return -1;
2622     }
2623 
2624     for (range = smiGetFirstRange(smiType);
2625 	 range;
2626 	 range = smiGetNextRange(range)) {
2627 	switch (basetype) {
2628 	case SMI_BASETYPE_INTEGER32:
2629 	    if (range->minValue.value.integer32 < min->value.integer32) {
2630 		min->value.integer32 = range->minValue.value.integer32;
2631 	    }
2632 	    if (range->maxValue.value.integer32 > max->value.integer32) {
2633 		max->value.integer32 = range->maxValue.value.integer32;
2634 	    }
2635 	    break;
2636 	case SMI_BASETYPE_INTEGER64:
2637 	    if (range->minValue.value.integer64 < min->value.integer64) {
2638 		min->value.integer64 = range->minValue.value.integer64;
2639 	    }
2640 	    if (range->maxValue.value.integer64 > max->value.integer64) {
2641 		max->value.integer64 = range->maxValue.value.integer64;
2642 	    }
2643 	    break;
2644 	case SMI_BASETYPE_UNSIGNED32:
2645 	    if (range->minValue.value.unsigned32 < min->value.unsigned32) {
2646 		min->value.unsigned32 = range->minValue.value.unsigned32;
2647 	    }
2648 	    if (range->maxValue.value.unsigned32 > max->value.unsigned32) {
2649 		max->value.unsigned32 = range->maxValue.value.unsigned32;
2650 	    }
2651 	    break;
2652 	case SMI_BASETYPE_UNSIGNED64:
2653 	    if (range->minValue.value.unsigned64 < min->value.unsigned64) {
2654 		min->value.unsigned64 = range->minValue.value.unsigned64;
2655 	    }
2656 	    if (range->maxValue.value.unsigned64 > max->value.unsigned64) {
2657 		max->value.unsigned64 = range->maxValue.value.unsigned64;
2658 	    }
2659 	    break;
2660 	default:
2661 	    fprintf(stderr, "smidump: unexpected basetype %d\n", basetype);
2662 	    return -1;
2663 	}
2664     }
2665 
2666     return 0;
2667 }
2668