/* objects.c - SMI object handling */
static char *rcsid
= "$Header: /f/osi/snmp/RCS/objects.c,v 7.14 91/02/22 09:43:44 mrose Interim $";
* $Header: /f/osi/snmp/RCS/objects.c,v 7.14 91/02/22 09:43:44 mrose Interim $
* Contributed by NYSERNet Inc. This work was partially supported by the
* U.S. Defense Advanced Research Projects Agency and the Rome Air Development
* Center of the U.S. Air Force Systems Command under contract number
* Revision 7.14 91/02/22 09:43:44 mrose
* Revision 7.13 90/12/11 21:56:34 mrose
* Revision 7.12 90/09/26 18:47:15 mrose
* Revision 7.11 90/08/30 15:11:09 mrose
* Revision 7.10 90/07/09 14:48:54 mrose
* Revision 7.9 90/06/21 21:26:23 mrose
* Revision 7.8 90/06/20 21:38:21 mrose
* Revision 7.7 90/06/12 09:22:06 mrose
* Revision 7.6 90/05/28 21:49:51 mrose
* Revision 7.5 90/05/13 16:18:14 mrose
* Revision 7.4 90/05/12 17:37:04 mrose
* Revision 7.3 90/02/19 15:54:04 mrose
* Revision 7.2 90/02/17 10:38:22 mrose
* Revision 7.1 90/01/11 18:34:23 mrose
* Revision 7.0 89/11/23 22:23:18 mrose
* Acquisition, use, and distribution of this module and related
* materials are subject to the restrictions of a license agreement.
* Consult the Preface in the User's Manual for the full terms of
static int once_only
= 0;
static char *compile_heap2
;
static unsigned int *compile_heap3
;
static OID compile_heap4
;
static OT Tbuckets
[TBUCKETS
];
for (c
= *(dp
= cp
= name
); *cp
; cp
++)
c
= tolower (*(dp
= cp
));
return (((c
- *dp
) & 0x1f) + (*(dp
+ 1) & 0x5f));
static int ot_compar (a
, b
)
int i
= oid_cmp ((*a
) -> ot_name
, (*b
) -> ot_name
);
&& (!((*a
) -> ot_access
& OT_XXX
)
|| !((*b
) -> ot_access
& OT_XXX
))) {
OID oid
= (*a
) -> ot_name
;
register unsigned int *ip
= oid
-> oid_elements
;
/* XXX: 0.0 is a special case */
if (oid
-> oid_nelem
== 2 && ip
[0] == 0 && ip
[1] == 0)
(void) sprintf (PY_pepy
+ strlen (PY_pepy
), ", ");
(void) sprintf (PY_pepy
, "duplicate objects: ");
(void) sprintf (PY_pepy
+ strlen (PY_pepy
), "\"%s\" and \"%s\"",
(*a
) -> ot_text
, (*b
) -> ot_text
);
(*a
) -> ot_access
|= OT_XXX
, (*b
) -> ot_access
|= OT_XXX
;
static char *roots
[] = { "ccitt", "iso", "joint-iso-ccitt" };
if ((fp
= fopen (file
, "r")) == NULL
&& (fp
= fopen (cp
= isodefile (file
, 0), "r")) == NULL
) {
(void) sprintf (PY_pepy
, "unable to read %s: %s",
cp
, sys_errname (errno
));
bzero ((char *) Tbuckets
, sizeof Tbuckets
);
if (fgets (buffer
, sizeof buffer
, fp
)
&& strncmp (buffer
, "--* compiled",
sizeof "--* compiled" - 1) == 0) {
if (sscanf (buffer
, "--* compiled %d %d %d", &i
, &j
, &k
) == 3) {
if ((compile_heap1
= (OT
) calloc ((unsigned) i
,
"out of memory allocating %d objects", i
);
if ((compile_heap2
= malloc ((unsigned) j
)) == NULL
) {
"out of memory allocating %d octets", j
);
if ((compile_heap3
= (unsigned int *)
calloc ((unsigned) k
, sizeof *compile_heap3
))
"out of memory allocating %d sub-identitifers",
if ((compile_heap4
= (OID
) calloc ((unsigned) i
,
"out of memory allocating %d identitifers",
for (ap
= roots
+ (sizeof roots
/ sizeof roots
[0]) - 1;
(void) sprintf (buffer
, "%d", ap
- roots
);
if (read_name (*ap
, buffer
) == NOTOK
) {
(void) sprintf (PY_pepy
, "only one compiled file is allowed");
while (fgets (buffer
, sizeof buffer
, fp
)) {
if (*buffer
== '#' || strncmp (buffer
, "--", 2) == 0)
if (cp
= index (buffer
, '\n'))
(void) strcpy (line
, buffer
);
bzero ((char *) vec
, sizeof vec
);
switch (str2vec (buffer
, vec
)) {
if (read_name (vec
[0], vec
[1]) == NOTOK
)
if (read_type (vec
) == NOTOK
)
(void) sprintf (PY_pepy
, "malformed line: \"%s\"", line
);
(void) sprintf (PY_pepy
, "unable to resolve object \"%s\"",
for (i
= 0; i
< TBUCKETS
; i
++)
if (ot
-> ot_name
== NULLOID
)
if (ot
-> ot_name
= resolve (ot
-> ot_id
, ot
))
for (i
= 0; i
< TBUCKETS
; i
++)
for (ot
= Tbuckets
[i
]; ot
&& ot
-> ot_text
; ot
= ot
-> ot_chain
)
if ((base
= (OT
*) malloc ((unsigned) (j
* sizeof *base
))) == NULL
) {
(void) sprintf (PY_pepy
, "out of memory");
for (i
= 0; i
< TBUCKETS
; i
++)
for (ot
= Tbuckets
[i
]; ot
&& ot
-> ot_text
; ot
= ot
-> ot_chain
)
qsort ((char *) base
, j
, sizeof *base
, ot_compar
);
(chain
= ot
) -> ot_next
= NULL
;
for (ot
= anchor
; ot
; ot
= ot
-> ot_next
) {
if ((oid
= str2oid (ot
-> ot_id
)) == NULLOID
) {
"invalid OID (%s) for \"%s\" in compiled file",
ot
-> ot_id
, ot
-> ot_text
);
ot
-> ot_name
= compile_heap4
++;
bcopy ((char *) oid
-> oid_elements
,
(char *) (ot
-> ot_name
-> oid_elements
(ot
-> ot_name
-> oid_nelem
= oid
-> oid_nelem
)
* sizeof *oid
-> oid_elements
);
compile_heap3
+= oid
-> oid_nelem
+ 1;
if ((ot
-> ot_name
= oid_cpy (oid
)) == NULLOID
) {
(void) sprintf (PY_pepy
, "out of memory");
if (add_objects_aux () == NOTOK
)
return (PY_pepy
[0] ? NOTOK
: OK
);
static int read_name (name
, value
)
(void) sprintf (PY_pepy
, "duplicate object \"%s\"", name
);
if (compile_flag
> 0 && compile_heap1
)
if ((ot
= (OT
) calloc (1, sizeof *ot
)) == NULL
) {
(void) sprintf (PY_pepy
, "out of memory");
if (compile_flag
> 0 && compile_heap2
) {
(void) strcpy (ot
-> ot_text
= compile_heap2
, name
);
compile_heap2
+= strlen (compile_heap2
) + 1;
(void) strcpy (ot
-> ot_id
= compile_heap2
, value
);
compile_heap2
+= strlen (compile_heap2
) + 1;
if ((ot
-> ot_text
= strdup (name
)) == NULL
|| (ot
-> ot_id
= strdup (value
)) == NULL
) {
(void) sprintf (PY_pepy
, "out of memory");
ot
-> ot_chain
= Tbuckets
[i
= THASH (name
)];
static int read_type (vec
)
(void) sprintf (PY_pepy
, "duplicate object \"%s\"", *vec
);
if (compile_flag
> 0 && compile_heap1
)
if ((ot
= (OT
) calloc (1, sizeof *ot
)) == NULL
) {
(void) sprintf (PY_pepy
, "out of memory");
if (compile_flag
> 0 && compile_heap2
) {
(void) strcpy (ot
-> ot_text
= compile_heap2
, *vec
++);
compile_heap2
+= strlen (compile_heap2
) + 1;
(void) strcpy (ot
-> ot_id
= compile_heap2
, *vec
++);
compile_heap2
+= strlen (compile_heap2
) + 1;
if ((ot
-> ot_text
= strdup (*vec
++)) == NULL
|| (ot
-> ot_id
= strdup (*vec
++)) == NULL
) {
(void) sprintf (PY_pepy
, "out of memory");
if ((ot
-> ot_syntax
= text2syn (*vec
)) == NULL
&& lexequ (*vec
, "Aggregate")
"warning: object \"%s\" has unknown SYNTAX \"%s\"\n",
if (lexequ (*vec
, "read-only") == 0)
ot
-> ot_access
= OT_RDONLY
;
if (lexequ (*vec
, "read-write") == 0)
ot
-> ot_access
= OT_RDWRITE
;
if (lexequ (*vec
, "write-only") == 0)
ot
-> ot_access
= OT_WRONLY
;
if (lexequ (*vec
, "not-accessible") && debug
)
"warning: object \"%s\" has unknown ACCESS \"%s\"\n",
if (lexequ (*vec
, "mandatory") == 0)
ot
-> ot_status
= OT_MANDATORY
;
if (lexequ (*vec
, "optional") == 0)
ot
-> ot_status
= OT_OPTIONAL
;
if (lexequ (*vec
, "deprecated") == 0)
ot
-> ot_status
= OT_DEPRECATED
;
if (lexequ (*vec
, "obsolete") && debug
)
"warning: object \"%s\" has unknown STATUS \"%s\"\n",
ot
-> ot_chain
= Tbuckets
[i
= THASH (ot
-> ot_text
)];
/* does not insert into THASH table... */
register OID oid
= ot
-> ot_name
;
if (oid_cmp (chain
-> ot_name
, oid
) < 0) {
(chain
= ot
) -> ot_next
= NULLOT
;
for (otp
= &anchor
; ot2
= *otp
; otp
= &ot2
-> ot_next
)
if (oid_cmp (ot2
-> ot_name
, oid
) > 0)
for (ot
= anchor
; ot
; ot
= ot
-> ot_next
)
ot
-> ot_sibling
= ot
-> ot_children
= NULLOT
;
return add_objects_aux ();
static int add_objects_aux ()
for (ot
= anchor
; ot
; ot
= ot
-> ot_next
) {
if (ot
-> ot_name
-> oid_nelem
<= 1)
for (oids
.oid_elements
= ot
-> ot_name
-> oid_elements
,
oids
.oid_nelem
= ot
-> ot_name
-> oid_nelem
- 1;
if (ot2
= name2obj (&oids
))
ot
-> ot_sibling
= ot2
-> ot_children
;
fprintf (stderr
, "no distant parent for %s",
sprintoid (ot
-> ot_name
));
register unsigned int *ip
,
unsigned int elements
[NELEM
+ 1];
for (cp
= name
+ strlen (name
) - 1; cp
>= name
; cp
--)
if (!isdigit (*cp
) && *cp
!= '.')
if (isdigit (*cp
) && cp
!= name
)
if (*cp
== NULL
) /* name */
if (cp
== name
) { /* 1.3.6.1.2.1.1.1.0 */
if ((i
= str2elem (cp
, elements
)) < 2)
if ((i
= str2elem (cp
+ 1, elements
)) < 1)
if ((oid
= resolve (name
, NULLOT
)) == NULLOID
)
if ((new = (OID
) malloc (sizeof *new)) == NULLOID
) {
if ((ip
= (unsigned int *) malloc ((unsigned) (i
+ j
+ 1) * sizeof *ip
))
new -> oid_elements
= ip
, new -> oid_nelem
= i
+ j
;
for (j
= 0, jp
= oid
-> oid_elements
; j
< oid
-> oid_nelem
; j
++, jp
++)
for (j
= 0, jp
= elements
; j
< i
; j
++, jp
++)
new -> oid_nelem
= ip
- new -> oid_elements
;
static OID
resolve (id
, ot
)
unsigned int elements
[NELEM
+ 1];
register OID oid
= &oids
;
oid
-> oid_elements
= elements
;
if (cp
= index (id
, '.'))
oid
-> oid_elements
[0] = atoi (id
);
if (ot2
== NULLOT
|| ot2
-> ot_name
== NULLOID
)
oid
-> oid_nelem
= ot2
-> ot_name
-> oid_nelem
;
bcopy ((char *) ot2
-> ot_name
-> oid_elements
,
(char *) oid
-> oid_elements
,
oid
-> oid_nelem
* sizeof *elements
);
if ((i
= str2elem (++cp
, oid
-> oid_elements
+ oid
-> oid_nelem
)) < 1)
if (ot
&& ot2
) { /* XXX: not normalized... */
ot
-> ot_sibling
= ot2
-> ot_children
;
/* partial matches are made only on leaf nodes... */
|| (i
= (ip
= oid
-> oid_elements
)[0])
>= (sizeof roots
/ sizeof roots
[0])
|| (ot
= text2obj (roots
[i
])) == NULL
)
if ((j
= (nm
= ot
-> ot_name
) -> oid_nelem
) > oid
-> oid_nelem
)
if (bcmp ((char *) ip
, (char *) (nm
-> oid_elements
+ i
),
if (oid
-> oid_nelem
== j
|| ot
-> ot_children
== NULLOT
ip
= oid
-> oid_elements
+ j
, i
= j
;
if (text
== NULL
|| once_only
== 0)
for (ot
= Tbuckets
[THASH (text
)];
ot
&& strcmp (ot
-> ot_text
, text
);
char *oid2ode_aux (oid
, quoted
)
register unsigned int *ip
;
static char buffer
[BUFSIZ
];
if ((oid
-> oid_nelem
== 2 /* XXX: 0.0 is a special case */
&& oid
-> oid_elements
[0] == 0
&& oid
-> oid_elements
[1] == 0)
|| (ot
= name2obj (oid
)) == NULLOT
)
(void) strcpy (bp
= buffer
, ot
-> ot_text
);
for (ip
= oid
-> oid_elements
+ (oid2
= ot
-> ot_name
) -> oid_nelem
,
i
= oid
-> oid_nelem
- oid2
-> oid_nelem
;
(void) sprintf (bp
, ".%u", *ip
);
static object_instance ois
;
if ((oi
-> oi_type
= name2obj (oi
-> oi_name
= oid
)) == NULLOT
)
static object_instance ois
;
for (ot
= anchor
; ot
; ot
= ot
-> ot_next
) {
if (oid
-> oid_nelem
< ot
-> ot_name
-> oid_nelem
|| bcmp ((char *) oid
-> oid_elements
,
(char *) ot
-> ot_name
-> oid_elements
,
ot
-> ot_name
-> oid_nelem
* sizeof oid
-> oid_elements
[0]))
if (oid_cmp (oid
, ot
-> ot_name
) > 0)
oi
-> oi_name
= (oi
-> oi_type
= ot
) -> ot_name
;
static object_instance ois
;
static OID oid
= NULLOID
;
oid_free (oid
), oid
= NULLOID
;
if ((oid
= text2oid (text
)) == NULLOID
)
if ((oi
-> oi_type
= name2obj (oi
-> oi_name
= oid
)) == NULLOT
) {
fprintf (stderr
, "got name \"%s\", but not object\n", text
);
for (i
= 0; i
< TBUCKETS
; i
++) {
for (ot
= Tbuckets
[i
]; ot
&& ot
-> ot_text
; ot
= ot
-> ot_chain
) {
printf ("Bucket %d:\n", i
), hit
= 1;
for (bp
= (ap
= roots
) + (sizeof roots
/ sizeof roots
[0]); ap
< bp
; ap
++) {
dump_object_by_tree (ot
, 0);
printf ("no object for root \"%s\"\n", *ap
);
dump_object_by_tree (ot
, i
)
dump_object_by_tree (ot
-> ot_children
, i
+ 1);
dump_object_by_tree (ot
-> ot_sibling
, i
);
for (ot
= anchor
; ot
; ot
= ot
-> ot_next
)
static dump_object (ot
, i
)
printf ("%*.*s%s %s %s %s %d %d 0x%x\n", i
, i
, "",
ot
-> ot_text
, ot
-> ot_id
, sprintoid (ot
-> ot_name
),
ot
-> ot_syntax
? ot
-> ot_syntax
-> os_name
: "NULL",
ot
-> ot_access
, ot
-> ot_status
, ot
-> ot_smux
);
if (p
= malloc ((unsigned) (strlen (s
) + 1)))