|
|
1.1 root 1: /* objects.c - SMI object handling */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/snmp/RCS/objects.c,v 7.10 90/07/09 14:48:54 mrose Exp $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/snmp/RCS/objects.c,v 7.10 90/07/09 14:48:54 mrose Exp $
9: *
10: * Contributed by NYSERNet Inc. This work was partially supported by the
11: * U.S. Defense Advanced Research Projects Agency and the Rome Air Development
12: * Center of the U.S. Air Force Systems Command under contract number
13: * F30602-88-C-0016.
14: *
15: *
16: * $Log: objects.c,v $
17: * Revision 7.10 90/07/09 14:48:54 mrose
18: * sync
19: *
20: * Revision 7.9 90/06/21 21:26:23 mrose
21: * 0.0
22: *
23: * Revision 7.8 90/06/20 21:38:21 mrose
24: * update
25: *
26: * Revision 7.7 90/06/12 09:22:06 mrose
27: * write-only
28: *
29: * Revision 7.6 90/05/28 21:49:51 mrose
30: * not-accessible
31: *
32: * Revision 7.5 90/05/13 16:18:14 mrose
33: * views
34: *
35: * Revision 7.4 90/05/12 17:37:04 mrose
36: * typo
37: *
38: * Revision 7.3 90/02/19 15:54:04 mrose
39: * touch-up
40: *
41: * Revision 7.2 90/02/17 10:38:22 mrose
42: * smux
43: *
44: * Revision 7.1 90/01/11 18:34:23 mrose
45: * real-sync
46: *
47: * Revision 7.0 89/11/23 22:23:18 mrose
48: * Release 6.0
49: *
50: */
51:
52: /*
53: * NOTICE
54: *
55: * Acquisition, use, and distribution of this module and related
56: * materials are subject to the restrictions of a license agreement.
57: * Consult the Preface in the User's Manual for the full terms of
58: * this agreement.
59: *
60: */
61:
62:
63: #include <ctype.h>
64: #include <stdio.h>
65: #include "objects.h"
66: #include "tailor.h"
67:
68: /* DATA */
69:
70: #define TBUCKETS 0x80
71:
72: static int once_only = 0;
73: static OT Tbuckets[TBUCKETS];
74:
75: static OT anchor;
76: static OT chain;
77:
78:
79: OID resolve ();
80:
81:
82: extern int errno;
83:
84: /* OBJECTS */
85:
86: static int THASH (name)
87: char *name;
88: {
89: char c;
90: register char *cp,
91: *dp;
92:
93: for (c = *(dp = cp = name); *cp; cp++)
94: if (isupper (*cp))
95: c = tolower (*(dp = cp));
96: if (*++dp)
97: return (((c - *dp) & 0x1f) + (*(dp + 1) & 0x5f));
98: else
99: return (c & 0x7f);
100: }
101:
102:
103: #define OT_XXX 0x04
104:
105: static int ot_compar (a, b)
106: OT *a,
107: *b;
108: {
109: int i = oid_cmp ((*a) -> ot_name, (*b) -> ot_name);
110:
111: if (i == 0
112: && (!((*a) -> ot_access & OT_XXX)
113: || !((*b) -> ot_access & OT_XXX))) {
114: OID oid = (*a) -> ot_name;
115: register unsigned int *ip = oid -> oid_elements;
116:
117: /* XXX: 0.0 is a special case */
118: if (oid -> oid_nelem == 2 && ip[0] == 0 && ip[1] == 0)
119: return 0;
120:
121: if (PY_pepy[0])
122: (void) sprintf (PY_pepy + strlen (PY_pepy), ", ");
123: else
124: (void) sprintf (PY_pepy, "duplicate objects: ");
125: (void) sprintf (PY_pepy + strlen (PY_pepy), "\"%s\" and \"%s\"",
126: (*a) -> ot_text, (*b) -> ot_text);
127: (*a) -> ot_access |= OT_XXX, (*b) -> ot_access |= OT_XXX;
128: }
129:
130: return i;
131: }
132:
133:
134: static char *roots[] = { "ccitt", "iso", "joint-iso-ccitt" };
135:
136: int readobjects (file)
137: char *file;
138: {
139: register int j;
140: int again,
141: hit,
142: i;
143: register char *cp,
144: **ap;
145: char buffer[BUFSIZ],
146: line[BUFSIZ],
147: *vec[NVEC + NSLACK + 1];
148: register OT ot,
149: *op,
150: *ep;
151: OT *base,
152: oz;
153: FILE *fp;
154:
155: if (once_only == 0) {
156: bzero ((char *) Tbuckets, sizeof Tbuckets);
157:
158: readsyntax ();
159:
160: for (ap = roots + (sizeof roots / sizeof roots[0]) - 1;
161: ap >= roots;
162: ap--) {
163: (void) sprintf (buffer, "%d", ap - roots);
164: if (read_name (*ap, buffer) == NOTOK)
165: return NOTOK;
166: }
167:
168: once_only = 1;
169: }
170:
171: if (file == NULL)
172: file = "objects.defs";
173: if ((fp = fopen (file, "r")) == NULL
174: && (fp = fopen (cp = isodefile (file, 0), "r")) == NULL) {
175: (void) sprintf (PY_pepy, "unable to read %s: %s",
176: cp, sys_errname (errno));
177: return NOTOK;
178: }
179:
180: while (fgets (buffer, sizeof buffer, fp)) {
181: if (*buffer == '#' || strncmp (buffer, "--", 2) == 0)
182: continue;
183: if (cp = index (buffer, '\n'))
184: *cp = NULL;
185: (void) strcpy (line, buffer);
186:
187: bzero ((char *) vec, sizeof vec);
188: switch (str2vec (buffer, vec)) {
189: case 0:
190: break;
191:
192: case 2:
193: if (read_name (vec[0], vec[1]) == NOTOK)
194: return NOTOK;
195: break;
196:
197: case 5:
198: if (read_type (vec) == NOTOK)
199: return NOTOK;
200: break;
201:
202: default:
203: (void) sprintf (PY_pepy, "malformed line: \"%s\"", line);
204: return NOTOK;
205: }
206: }
207:
208: (void) fclose (fp);
209:
210: hit = 1, oz = NULLOT;
211: do {
212: if (!hit) {
213: (void) sprintf (PY_pepy, "unable to resolve object \"%s\"",
214: oz -> ot_text);
215: return NOTOK;
216: }
217:
218: again = hit = 0;
219:
220: for (i = 0; i < TBUCKETS; i++)
221: for (ot = Tbuckets[i]; ot && ot -> ot_text; ot = ot -> ot_chain)
222: if (ot -> ot_name == NULLOID)
223: if (ot -> ot_name = resolve (ot -> ot_id, ot))
224: hit = 1;
225: else
226: oz = ot, again = 1;
227: } while (again);
228:
229: #ifdef notdef
230: dump_objects_by_text ();
231: #endif
232:
233: j = 0;
234: for (i = 0; i < TBUCKETS; i++)
235: for (ot = Tbuckets[i]; ot && ot -> ot_text; ot = ot -> ot_chain)
236: j++;
237:
238: /* j > 1 ALWAYS */
239:
240: if ((base = (OT *) malloc ((unsigned) (j * sizeof *base))) == NULL) {
241: (void) sprintf (PY_pepy, "out of memory");
242: return NOTOK;
243: }
244:
245: op = base;
246: for (i = 0; i < TBUCKETS; i++)
247: for (ot = Tbuckets[i]; ot && ot -> ot_text; ot = ot -> ot_chain)
248: *op++ = ot;
249: ep = op;
250:
251: PY_pepy[0] = NULL;
252: qsort ((char *) base, j, sizeof *base, ot_compar);
253:
254: op = base;
255: anchor = ot = *op++;
256: while (op < ep) {
257: ot -> ot_next = *op;
258: ot = *op++;
259: }
260: (chain = ot) -> ot_next = NULL;
261:
262: free ((char *) base);
263:
264: return (PY_pepy[0] ? NOTOK : OK);
265: }
266:
267: /* */
268:
269: static int read_name (name, value)
270: char *name,
271: *value;
272: {
273: int i;
274: register OT ot;
275:
276: if (text2obj (name)) {
277: (void) sprintf (PY_pepy, "duplicate object \"%s\"", name);
278: return NOTOK;
279: }
280:
281: if ((ot = (OT) calloc (1, sizeof *ot)) == NULL) {
282: (void) sprintf (PY_pepy, "out of memory");
283: return NOTOK;
284: }
285: if ((ot -> ot_text = strdup (name)) == NULL
286: || (ot -> ot_id = strdup (value)) == NULL) {
287: (void) sprintf (PY_pepy, "out of memory");
288: return NOTOK;
289: }
290:
291: ot -> ot_chain = Tbuckets[i = THASH (name)];
292: Tbuckets[i] = ot;
293:
294: return OK;
295: }
296:
297: /* */
298:
299: static int read_type (vec)
300: char **vec;
301: {
302: int i;
303: register OT ot;
304:
305: if (text2obj (*vec)) {
306: (void) sprintf (PY_pepy, "duplicate object \"%s\"", *vec);
307: return NOTOK;
308: }
309:
310: if ((ot = (OT) calloc (1, sizeof *ot)) == NULL) {
311: (void) sprintf (PY_pepy, "out of memory");
312: return NOTOK;
313: }
314: if ((ot -> ot_text = strdup (*vec++)) == NULL
315: || (ot -> ot_id = strdup (*vec++)) == NULL) {
316: (void) sprintf (PY_pepy, "out of memory");
317: return NOTOK;
318: }
319: if ((ot -> ot_syntax = text2syn (*vec)) == NULL
320: && lexequ (*vec, "Aggregate")
321: && debug)
322: fprintf (stderr,
323: "warning: object \"%s\" has unknown SYNTAX \"%s\"\n",
324: ot -> ot_text, *vec);
325: vec++;
326:
327: if (lexequ (*vec, "read-only") == 0)
328: ot -> ot_access = OT_RDONLY;
329: else
330: if (lexequ (*vec, "read-write") == 0)
331: ot -> ot_access = OT_RDWRITE;
332: else
333: if (lexequ (*vec, "write-only") == 0)
334: ot -> ot_access = OT_WRONLY;
335: else
336: if (lexequ (*vec, "not-accessible") && debug)
337: fprintf (stderr,
338: "warning: object \"%s\" has unknown ACCESS \"%s\"\n",
339: ot -> ot_text, *vec);
340: vec++;
341:
342: if (lexequ (*vec, "mandatory") == 0)
343: ot -> ot_status = OT_MANDATORY;
344: else
345: if (lexequ (*vec, "optional") == 0)
346: ot -> ot_status = OT_OPTIONAL;
347: else
348: if (lexequ (*vec, "deprecated") == 0)
349: ot -> ot_status = OT_DEPRECATED;
350: else
351: if (lexequ (*vec, "obsolete") && debug)
352: fprintf (stderr,
353: "warning: object \"%s\" has unknown STATUS \"%s\"\n",
354: ot -> ot_text, *vec);
355: vec++;
356:
357: ot -> ot_chain = Tbuckets[i = THASH (ot -> ot_text)];
358: Tbuckets[i] = ot;
359:
360: return OK;
361: }
362:
363: /* */
364:
365: /* does not insert into THASH table... */
366:
367: int add_objects (ot)
368: register OT ot;
369: {
370: register OID oid = ot -> ot_name;
371: register OT ot2,
372: *otp;
373:
374: if (oid_cmp (chain -> ot_name, oid) < 0) {
375: chain -> ot_next = ot;
376: (chain = ot) -> ot_next = NULLOT;
377: }
378: else {
379: for (otp = &anchor; ot2 = *otp; otp = &ot2 -> ot_next)
380: if (oid_cmp (ot2 -> ot_name, oid) > 0)
381: break;
382: ot -> ot_next = ot2;
383: *otp = ot;
384: }
385:
386: for (ot = anchor; ot; ot = ot -> ot_next)
387: ot -> ot_sibling = ot -> ot_children = NULLOT;
388:
389: for (ot = anchor; ot; ot = ot -> ot_next) {
390: OIDentifier oids;
391:
392: if (ot -> ot_name -> oid_nelem <= 1)
393: continue;
394: ot2 = NULLOT;
395: for (oids.oid_elements = ot -> ot_name -> oid_elements,
396: oids.oid_nelem = ot -> ot_name -> oid_nelem - 1;
397: oids.oid_nelem > 0;
398: oids.oid_nelem--)
399: if (ot2 = name2obj (&oids))
400: break;
401: if (ot2) {
402: ot -> ot_sibling = ot2 -> ot_children;
403: ot2 -> ot_children = ot;
404: }
405: else
406: if (debug)
407: fprintf (stderr, "no distant parent for %s",
408: sprintoid (ot -> ot_name));
409: }
410: }
411:
412: /* */
413:
414: OID text2oid (name)
415: char *name;
416: {
417: int i,
418: j;
419: register unsigned int *ip,
420: *jp;
421: unsigned int elements[NELEM + 1];
422: register char *cp;
423: OID oid,
424: new;
425:
426: for (cp = name + strlen (name) - 1; cp >= name; cp--)
427: if (!isdigit (*cp) && *cp != '.')
428: break;
429: cp++;
430: if (isdigit (*cp) && cp != name)
431: for (cp++; *cp; cp++)
432: if (*cp == '.')
433: break;
434:
435: if (*cp == NULL) /* name */
436: i = 0;
437: else
438: if (cp == name) { /* 1.3.6.1.2.1.1.1.0 */
439: if ((i = str2elem (cp, elements)) < 2)
440: return NULL;
441: }
442: else /* name.numbers */
443: if ((i = str2elem (cp + 1, elements)) < 1)
444: return NULL;
445:
446: if (cp != name) {
447: *cp = NULL;
448: if ((oid = resolve (name, NULLOT)) == NULLOID)
449: return NULL;
450: if (i == 0)
451: return oid;
452:
453: j = oid -> oid_nelem;
454: }
455: else
456: oid = NULL, j = 0;
457:
458: if ((new = (OID) malloc (sizeof *new)) == NULLOID) {
459: oid_free (oid);
460: return NULL;
461: }
462: if ((ip = (unsigned int *) malloc ((unsigned) (i + j + 1) * sizeof *ip))
463: == NULL) {
464: oid_free (oid);
465: free ((char *) new);
466: }
467: new -> oid_elements = ip, new -> oid_nelem = i + j;
468:
469: if (oid) {
470: for (j = 0, jp = oid -> oid_elements; j < oid -> oid_nelem; j++, jp++)
471: *ip++ = *jp;
472:
473: oid_free (oid);
474: }
475: if (i > 0)
476: for (j = 0, jp = elements; j < i; j++, jp++)
477: *ip++ = *jp;
478:
479: new -> oid_nelem = ip - new -> oid_elements;
480:
481: return new;
482: }
483:
484:
485: static OID resolve (id, ot)
486: char *id;
487: register OT ot;
488: {
489: int i;
490: unsigned int elements[NELEM + 1];
491: register char *cp;
492: register OT ot2;
493: struct OIDentifier oids;
494: register OID oid = &oids;
495:
496: oid -> oid_elements = elements;
497:
498: if (cp = index (id, '.'))
499: *cp = NULL;
500: if (isdigit (*id)) {
501: ot2 = NULLOT;
502: oid -> oid_nelem = 1;
503: oid -> oid_elements[0] = atoi (id);
504: if (cp)
505: *cp = '.';
506: }
507: else {
508: ot2 = text2obj (id);
509: if (cp)
510: *cp = '.';
511: if (ot2 == NULLOT || ot2 -> ot_name == NULLOID)
512: return NULLOID;
513:
514: oid -> oid_nelem = ot2 -> ot_name -> oid_nelem;
515: bcopy ((char *) ot2 -> ot_name -> oid_elements,
516: (char *) oid -> oid_elements,
517: oid -> oid_nelem * sizeof *elements);
518: }
519:
520: if (cp) {
521: if ((i = str2elem (++cp, oid -> oid_elements + oid -> oid_nelem)) < 1)
522: return NULLOID;
523: oid -> oid_nelem += i;
524: if (ot && ot2) { /* XXX: not normalized... */
525: ot -> ot_sibling = ot2 -> ot_children;
526: ot2 -> ot_children = ot;
527: }
528: }
529:
530: return oid_cpy (oid);
531: }
532:
533: /* */
534:
535: /* partial matches are made only on leaf nodes... */
536:
537: OT name2obj (oid)
538: OID oid;
539: {
540: register int i,
541: j;
542: register unsigned *ip;
543: register OID nm;
544: register OT ot;
545:
546: if (oid == NULLOID
547: || oid -> oid_nelem < 1
548: || (i = (ip = oid -> oid_elements)[0])
549: >= (sizeof roots / sizeof roots[0])
550: || (ot = text2obj (roots[i])) == NULL)
551: return NULLOT;
552:
553: i = 0;
554: while (ot) {
555: if ((j = (nm = ot -> ot_name) -> oid_nelem) > oid -> oid_nelem)
556: return NULLOT;
557:
558: if (bcmp ((char *) ip, (char *) (nm -> oid_elements + i),
559: (j - i) * sizeof *ip))
560: ot = ot -> ot_sibling;
561: else
562: if (oid -> oid_nelem == j
563: || ot -> ot_children == NULLOT
564: || ot -> ot_smux)
565: break;
566: else {
567: ot = ot -> ot_children;
568: ip = oid -> oid_elements + j, i = j;
569: }
570: }
571:
572: return ot;
573: }
574:
575: /* */
576:
577: OT text2obj (text)
578: char *text;
579: {
580: register OT ot;
581:
582: if (text == NULL || once_only == 0)
583: return NULLOT;
584:
585: for (ot = Tbuckets[THASH (text)];
586: ot && strcmp (ot -> ot_text, text);
587: ot = ot -> ot_chain)
588: continue;
589:
590: return ot;
591: }
592:
593: /* */
594:
595: /* ARGSUSED */
596:
597: char *oid2ode_aux (oid, quoted)
598: OID oid;
599: int quoted;
600: {
601: register int i;
602: register char *bp;
603: register unsigned int *ip;
604: register OID oid2;
605: register OT ot;
606: static char buffer[BUFSIZ];
607:
608: if ((oid -> oid_nelem == 2 /* XXX: 0.0 is a special case */
609: && oid -> oid_elements[0] == 0
610: && oid -> oid_elements[1] == 0)
611: || (ot = name2obj (oid)) == NULLOT)
612: return sprintoid (oid);
613:
614: (void) strcpy (bp = buffer, ot -> ot_text);
615: bp += strlen (bp);
616: for (ip = oid -> oid_elements + (oid2 = ot -> ot_name) -> oid_nelem,
617: i = oid -> oid_nelem - oid2 -> oid_nelem;
618: i-- > 0;
619: ip++) {
620: (void) sprintf (bp, ".%u", *ip);
621: bp += strlen (bp);
622: }
623:
624: return buffer;
625: }
626:
627: /* */
628:
629: OI name2inst (oid)
630: OID oid;
631: {
632: static object_instance ois;
633: register OI oi = &ois;
634:
635: if ((oi -> oi_type = name2obj (oi -> oi_name = oid)) == NULLOT)
636: return NULLOI;
637:
638: return oi;
639: }
640:
641:
642: OI next2inst (oid)
643: OID oid;
644: {
645: static object_instance ois;
646: register OI oi = &ois;
647: register OT ot;
648:
649: for (ot = anchor; ot; ot = ot -> ot_next) {
650: if (ot -> ot_smux) {
651: if (oid -> oid_nelem < ot -> ot_name -> oid_nelem
652: || bcmp ((char *) oid -> oid_elements,
653: (char *) ot -> ot_name -> oid_elements,
654: ot -> ot_name -> oid_nelem
655: * sizeof oid -> oid_elements[0]))
656: continue;
657: }
658: else
659: if (oid_cmp (oid, ot -> ot_name) > 0)
660: continue;
661:
662: oi -> oi_name = (oi -> oi_type = ot) -> ot_name;
663: return oi;
664: }
665:
666: return NULLOI;
667: }
668:
669: /* */
670:
671: OI text2inst (text)
672: char *text;
673: {
674: static object_instance ois;
675: register OI oi = &ois;
676: static OID oid = NULLOID;
677:
678: if (oid)
679: oid_free (oid), oid = NULLOID;
680:
681: if ((oid = text2oid (text)) == NULLOID)
682: return NULLOI;
683: if ((oi -> oi_type = name2obj (oi -> oi_name = oid)) == NULLOT) {
684: if (debug)
685: fprintf (stderr, "got name \"%s\", but not object\n", text);
686: return NULLOI;
687: }
688:
689: return oi;
690: }
691:
692: /* DUMP */
693:
694: #ifdef DEBUG
695: dump_objects_by_text ()
696: {
697: int hit;
698: register int i;
699: register OT ot;
700:
701: for (i = 0; i < TBUCKETS; i++) {
702: hit = 0;
703: for (ot = Tbuckets[i]; ot && ot -> ot_text; ot = ot -> ot_chain) {
704: if (!hit)
705: printf ("Bucket %d:\n", i), hit = 1;
706: dump_object (ot, 2);
707: }
708: }
709:
710: printf ("///////\n");
711: }
712:
713:
714: dump_objects_by_tree ()
715: {
716: register char **ap;
717: char **bp;
718: register OT ot;
719:
720: for (bp = (ap = roots) + (sizeof roots / sizeof roots[0]); ap < bp; ap++) {
721: if (ot = text2obj (*ap))
722: dump_object_by_tree (ot, 0);
723: else
724: printf ("no object for root \"%s\"\n", *ap);
725: }
726:
727: printf ("///////\n");
728: }
729:
730:
731: dump_object_by_tree (ot, i)
732: register OT ot;
733: int i;
734: {
735: if (ot == NULL)
736: return;
737:
738: dump_object (ot, i);
739: dump_object_by_tree (ot -> ot_children, i + 1);
740: dump_object_by_tree (ot -> ot_sibling, i);
741: }
742:
743:
744: dump_objects_by_xxx ()
745: {
746: register OT ot;
747:
748: for (ot = anchor; ot; ot = ot -> ot_next)
749: dump_object (ot, 0);
750:
751: printf ("///////\n");
752: }
753:
754:
755: static dump_object (ot, i)
756: register OT ot;
757: int i;
758: {
759: printf ("%*.*s%s %s %s %s %d %d 0x%x\n", i, i, "",
760: ot -> ot_text, ot -> ot_id, sprintoid (ot -> ot_name),
761: ot -> ot_syntax ? ot -> ot_syntax -> os_name : "NULL",
762: ot -> ot_access, ot -> ot_status, ot -> ot_smux);
763: }
764: #endif
765:
766: /* MISCELLANY */
767:
768: char *strdup (s)
769: char *s;
770: {
771: char *p;
772:
773: if (p = malloc ((unsigned) (strlen (s) + 1)))
774: (void) strcpy (p, s);
775:
776: return p;
777: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.