Net2/usr/src/contrib/isode/snmp/syntax.c
/* syntax.c - SMI syntax handling */
#ifndef lint
static char *rcsid = "$Header: /f/osi/snmp/RCS/syntax.c,v 7.19 91/02/22 09:44:38 mrose Interim $";
#endif
/*
* $Header: /f/osi/snmp/RCS/syntax.c,v 7.19 91/02/22 09:44:38 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
* F30602-88-C-0016.
*
*
* $Log: syntax.c,v $
* Revision 7.19 91/02/22 09:44:38 mrose
* Interim 6.8
*
* Revision 7.18 91/01/13 11:05:45 mrose
* update
*
* Revision 7.17 91/01/12 21:22:58 mrose
* update
*
* Revision 7.16 91/01/11 15:35:36 mrose
* sets
*
* Revision 7.15 90/12/18 10:14:07 mrose
* update
*
* Revision 7.14 90/11/20 15:32:55 mrose
* update
*
* Revision 7.13 90/11/04 19:16:36 mrose
* update
*
* Revision 7.12 90/10/29 18:39:12 mrose
* updates
*
* Revision 7.11 90/10/23 20:37:17 mrose
* update
*
* Revision 7.10 90/08/18 00:44:42 mrose
* touch-up
*
* Revision 7.9 90/08/08 14:01:39 mrose
* stuff
*
* Revision 7.8 90/07/09 14:49:41 mrose
* sync
*
* Revision 7.7 90/04/18 08:52:03 mrose
* oid_normalize
*
* Revision 7.6 90/04/08 03:23:20 mrose
* touch-up
*
* Revision 7.5 90/03/23 17:27:35 mrose
* update
*
* Revision 7.4 90/03/08 08:05:25 mrose
* touch-up
*
* Revision 7.3 90/02/19 19:23:14 mrose
* again
*
* Revision 7.2 90/02/19 19:17:11 mrose
* again
*
* Revision 7.1 90/01/11 18:34:48 mrose
* real-sync
*
* Revision 7.0 89/11/23 22:23:32 mrose
* Release 6.0
*
*/
/*
* NOTICE
*
* 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
* this agreement.
*
*/
#include <ctype.h>
#include <stdio.h>
#include "SNMP-types.h"
#include "objects.h"
#include "tailor.h"
#include "internet.h"
#include "clns.h"
/* DATA */
#define MAXSYN 50
static object_syntax syntaxes[MAXSYN + 1];
static OS synlast = syntaxes;
/* INTEGER */
static int integer_encode (x, pe)
integer *x;
PE *pe;
{
if ((*pe = int2prim (*x)) == NULLPE)
return NOTOK;
return OK;
}
static int integer_decode (x, pe)
integer **x;
PE pe;
{
integer i = prim2num (pe);
if (i == NOTOK && pe -> pe_errno != PE_ERR_NONE)
return NOTOK;
if ((*x = (integer *) malloc (sizeof **x)) == NULL)
return NOTOK;
**x = i;
return OK;
}
static int integer_free (x)
integer *x;
{
free ((char *) x);
}
static int integer_parse (x, s)
integer **x;
char *s;
{
long l;
if (sscanf (s, "%ld", &l) != 1)
return NOTOK;
if ((*x = (integer *) malloc (sizeof **x)) == NULL)
return NOTOK;
**x = (integer) l;
return OK;
}
/* ARGSUSED */
static int integer_print (x, os)
integer *x;
OS os;
{
printf ("%d", *x);
}
/* ARGSUSED */
static int services_print (x, os)
integer *x;
OS os;
{
printf ("%s", sprintb ((int) *x,
"\020\01physical\02datalink/subnetwork\03internet\04transport\05session\06presentation\07application"));
}
/* ARGSUSED */
static int privs_print (x, os)
integer *x;
OS os;
{
printf ("%s", sprintb ((int) *x,
"\020\01get\02get-next\03get-response\04set\05trap"));
}
static add_integer ()
{
(void) add_syntax ("INTEGER", integer_encode, integer_decode, integer_free,
integer_parse, integer_print);
(void) add_syntax ("Services", integer_encode, integer_decode,
integer_free, integer_parse, services_print);
(void) add_syntax ("Privileges", integer_encode, integer_decode,
integer_free, integer_parse, privs_print);
}
/* OCTET STRING */
static int string_encode (x, pe)
struct qbuf *x;
PE *pe;
{
if ((*pe = qb2prim_aux (x, PE_CLASS_UNIV, PE_PRIM_OCTS, 0)) == NULLPE)
return NOTOK;
return OK;
}
static int string_decode (x, pe)
struct qbuf **x;
PE pe;
{
struct qbuf *qb = prim2qb (pe);
if (qb == NULL)
return NOTOK;
*x = qb;
return OK;
}
static int string_parse (x, s)
struct qbuf **x;
char *s;
{
struct qbuf *qb;
if (strncmp (s, "0x", 2) == 0) {
int len;
char *p;
s += 2;
if ((len = strlen (s)) % 3 != 2)
return NOTOK;
len /= 3, len++;
if ((qb = str2qb (NULLCP, len, 1)) == NULL)
return NOTOK;
p = qb -> qb_forw -> qb_data;
while (*s) {
int i;
if (sscanf (s, "%x", &i) != 1) {
oops: ;
qb_free (qb);
return NOTOK;
}
*p++ = i & 0xff;
s += 2;
if (*s && *s++ != ':')
goto oops;
}
}
else
if ((qb = str2qb (s, strlen (s), 1)) == NULL)
return NOTOK;
*x = qb;
return OK;
}
/* ARGSUSED */
static int string_print (x, os)
struct qbuf *x;
OS os;
{
register char *cp,
*ep;
char *p;
register struct qbuf *qb;
p = "0x";
for (qb = x -> qb_forw; qb != x; qb = qb -> qb_forw)
for (ep = (cp = qb -> qb_data) + qb -> qb_len; cp < ep; cp++) {
printf ("%s%02x", p, *cp & 0xff);
p = ":";
}
}
/* ARGSUSED */
static int string_display (x, os)
struct qbuf *x;
OS os;
{
register struct qbuf *qb;
printf ("\"");
for (qb = x -> qb_forw; qb != x; qb = qb -> qb_forw)
printf ("%*.*s", qb -> qb_len, qb -> qb_len, qb -> qb_data);
printf ("\"");
}
static add_string ()
{
(void) add_syntax ("OctetString", string_encode, string_decode, qb_free,
string_parse, string_print);
(void) add_syntax ("DisplayString", string_encode, string_decode, qb_free,
string_parse, string_display);
(void) add_syntax ("PhysAddress", string_encode, string_decode, qb_free,
string_parse, string_print);
}
/* OBJECT IDENTIFIER */
static int object_encode (x, pe)
OID x;
PE *pe;
{
if ((*pe = oid2prim (x)) == NULLPE)
return NOTOK;
return OK;
}
static int object_decode (x, pe)
OID *x;
PE pe;
{
OID oid = prim2oid (pe);
if (oid == NULLOID || (*x = oid_cpy (oid)) == NULLOID)
return NOTOK;
return OK;
}
static int object_parse (x, s)
OID *x;
char *s;
{
OID oid = text2oid (s);
if (oid == NULL)
return NOTOK;
*x = oid;
return OK;
}
/* ARGSUSED */
static int object_print (x, os)
OID x;
OS os;
{
char *cp,
ode[BUFSIZ];
(void) strcpy (ode, oid2ode (x));
printf ("%s", ode);
if (strcmp (ode, cp = sprintoid (x)))
printf (" (%s)", cp);
}
static add_object ()
{
(void) add_syntax ("ObjectID", object_encode, object_decode, oid_free,
object_parse, object_print);
}
/* NULL */
/* ARGSUSED */
static int null_encode (x, pe)
char *x;
PE *pe;
{
if ((*pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_NULL)) == NULLPE)
return NOTOK;
return OK;
}
/* ARGSUSED */
static int null_decode (x, pe)
char **x;
PE pe;
{
if ((*x = (char *) calloc (1, sizeof **x)) == NULL)
return NOTOK;
return OK;
}
static int null_free (x)
char *x;
{
free ((char *) x);
}
static int null_parse (x, s)
char **x;
char *s;
{
if (lexequ (s, "NULL"))
return NOTOK;
if ((*x = (char *) calloc (1, sizeof **x)) == NULL)
return NOTOK;
return OK;
}
/* ARGSUSED */
static int null_print (x, os)
char *x;
OS os;
{
printf ("NULL");
}
static add_null ()
{
(void) add_syntax ("NULL", null_encode, null_decode, null_free, null_parse,
null_print);
}
/* IpAddress */
static int ipaddr_encode (x, pe)
struct sockaddr_in *x;
PE *pe;
{
if ((*pe = str2prim ((char *) &x -> sin_addr, 4, PE_CLASS_APPL, 0))
== NULLPE)
return NOTOK;
return OK;
}
static int ipaddr_decode (x, pe)
struct sockaddr_in **x;
PE pe;
{
struct type_SNMP_IpAddress *ip;
struct qbuf *qb;
struct sockaddr_in *isock;
if (decode_SNMP_IpAddress (pe, 1, NULLIP, NULLVP, &ip) == NOTOK)
return NOTOK;
if (qb_pullup (ip) == NOTOK
|| (isock = (struct sockaddr_in *) calloc (1, sizeof *isock))
== NULL) {
free_SNMP_IpAddress (ip);
return NOTOK;
}
if ((qb = ip -> qb_forw) -> qb_len != 4) {
free ((char *) isock);
free_SNMP_IpAddress (ip);
return NOTOK;
}
isock -> sin_family = AF_INET;
bcopy (qb -> qb_data,
(char *) &isock -> sin_addr,
sizeof isock -> sin_addr);
*x = isock;
free_SNMP_IpAddress (ip);
return OK;
}
static int ipaddr_free (x)
struct sockaddr_in *x;
{
free ((char *) x);
}
static int ipaddr_parse (x, s)
struct sockaddr_in **x;
char *s;
{
register struct hostent *hp = gethostbystring (s);
register struct sockaddr_in *isock;
if (hp == NULL)
return NOTOK;
if ((isock = (struct sockaddr_in *) calloc (1, sizeof *isock)) == NULL)
return NOTOK;
isock -> sin_family = AF_INET;
inaddr_copy (hp, isock);
*x = isock;
return OK;
}
/* ARGSUSED */
static int ipaddr_print (x, os)
struct sockaddr_in *x;
OS os;
{
printf ("%s", inet_ntoa (x -> sin_addr));
}
static add_ipaddr ()
{
(void) add_syntax ("IpAddress", ipaddr_encode, ipaddr_decode, ipaddr_free,
ipaddr_parse, ipaddr_print);
}
/* NetworkAddress */
/* good enough for now (and probably forever)... */
static add_netaddr ()
{
(void) add_syntax ("NetworkAddress", ipaddr_encode, ipaddr_decode,
ipaddr_free, ipaddr_parse, ipaddr_print);
}
/* UNSIGNED LONGs */
u_long prim2ulong (pe) /* also used in SNMP-capable gawk... */
register PE pe;
{
register u_long i;
register PElementData dp,
ep;
if (pe -> pe_form != PE_FORM_PRIM || (dp = pe -> pe_prim) == NULLPED)
return pe_seterr (pe, PE_ERR_PRIM, 0);
if (pe -> pe_len > sizeof (i) + 1)
return pe_seterr (pe, PE_ERR_OVER, 0);
if (pe -> pe_len == sizeof (i) + 1 && (*dp & 0x7f))
return pe_seterr (pe, PE_ERR_OVER, 0);
if (*dp & 0x80)
return pe_seterr (pe, PE_ERR_SIGNED, 0);
pe -> pe_errno = PE_ERR_NONE; /* in case result is ZERO-valued */
i = 0L;
for (ep = dp + pe -> pe_len; dp < ep;)
i = (i << 8) | (*dp++ & 0xff);
return i;
}
static PE ulong2prim (i, class, id)
register u_long i;
PElementClass class;
PElementID id;
{
int extend;
register int n;
register u_long mask;
register PElementData dp;
register PE pe;
if ((pe = pe_alloc (class, PE_FORM_PRIM, id)) == NULLPE)
return NULLPE;
mask = 0xff << (((n = sizeof i) - 1) * 8);
while (n > 1 && (i & mask) == 0)
mask >>= 8, n--;
extend = (i & (0x80 << ((n - 1) * 8))) ? 1 : 0;
if ((pe -> pe_prim = PEDalloc (n + extend)) == NULLPED) {
pe_free (pe);
return NULLPE;
}
for (dp = pe -> pe_prim + (pe -> pe_len = n + extend); n-- > 0; i >>= 8)
*--dp = i & 0xff;
if (extend)
*--dp = 0x00;
return pe;
}
/* Counter */
static int counter_encode (x, pe)
u_long *x;
PE *pe;
{
if ((*pe = ulong2prim (*x, PE_CLASS_APPL, 1)) == NULLPE)
return NOTOK;
return OK;
}
static int counter_decode (x, pe)
u_long **x;
PE pe;
{
u_long i = prim2ulong (pe);
if (i == 0 && pe -> pe_errno != PE_ERR_NONE)
return NOTOK;
if ((*x = (u_long *) malloc (sizeof **x)) == NULL)
return NOTOK;
**x = i;
return OK;
}
static int counter_free (x)
u_long *x;
{
free ((char *) x);
}
static int counter_parse (x, s)
u_long **x;
char *s;
{
u_long i;
if (sscanf (s, "%U", &i) != 1)
return NOTOK;
if ((*x = (u_long *) malloc (sizeof **x)) == NULL)
return NOTOK;
**x = i;
return OK;
}
/* ARGSUSED */
static int counter_print (x, os)
u_long *x;
OS os;
{
printf ("%U", *x);
}
static add_counter ()
{
(void) add_syntax ("Counter", counter_encode, counter_decode, counter_free,
counter_parse, counter_print);
}
/* Gauge */
static int gauge_encode (x, pe)
u_long *x;
PE *pe;
{
if ((*pe = ulong2prim (*x, PE_CLASS_APPL, 2)) == NULLPE)
return NOTOK;
return OK;
}
static add_gauge ()
{
(void) add_syntax ("Gauge", gauge_encode, counter_decode, counter_free,
counter_parse, counter_print);
}
/* TimeTicks */
static int timeticks_encode (x, pe)
u_long *x;
PE *pe;
{
if ((*pe = ulong2prim (*x, PE_CLASS_APPL, 3)) == NULLPE)
return NOTOK;
return OK;
}
/* ARGSUSED */
static int timeticks_print (x, os)
u_long *x;
OS os;
{
u_long d,
h,
m,
s,
ds;
ds = *x;
s = ds / 100, ds = ds % 100;
m = s / 60, s = s % 60;
h = m / 60, m = m % 60;
d = h / 24, h = h % 24;
if (d > 0)
printf ("%d days, ", d);
if (d > 0 || h > 0)
printf ("%d hours, ", h);
if (d > 0 || h > 0 || m > 0)
printf ("%d minutes, ", m);
printf ("%d", s);
if (ds > 0)
printf (".%02d", ds);
printf (" seconds (%U timeticks)", *x);
}
static add_timeticks ()
{
(void) add_syntax ("TimeTicks", timeticks_encode, counter_decode,
counter_free, counter_parse, timeticks_print);
}
/* CnlpAddress */
static int clnpaddr_encode (x, pe)
struct sockaddr_iso *x;
PE *pe;
{
char buffer[sizeof x -> siso_data + 1];
buffer[0] = x -> siso_nlen & 0xff;
bcopy (x -> siso_data, buffer + 1, (int) x -> siso_nlen);
if ((*pe = str2prim (buffer, (int) (x -> siso_nlen + 1), PE_CLASS_APPL,
5)) == NULLPE)
return NOTOK;
return OK;
}
static int clnpaddr_decode (x, pe)
struct sockaddr_iso **x;
PE pe;
{
int len;
struct type_SNMP_ClnpAddress *clnp;
struct qbuf *qb;
struct sockaddr_iso *isock;
if (decode_SNMP_ClnpAddress (pe, 1, NULLIP, NULLVP, &clnp) == NOTOK)
return NOTOK;
if (qb_pullup (clnp) == NOTOK
|| (isock = (struct sockaddr_iso *) calloc (1, sizeof *isock))
== NULL) {
free_SNMP_ClnpAddress (clnp);
return NOTOK;
}
qb = clnp -> qb_forw;
isock -> siso_family = AF_ISO;
if ((len = qb -> qb_data[0] & 0xff) >= qb -> qb_len)
len = qb -> qb_len - 1;
bcopy (qb -> qb_data + 1, isock -> siso_data,
(int) (isock -> siso_nlen = len));
*x = isock;
free_SNMP_ClnpAddress (clnp);
return OK;
}
static int clnpaddr_free (x)
struct sockaddr_iso *x;
{
free ((char *) x);
}
static int clnpaddr_parse (x, s)
struct sockaddr_iso **x;
char *s;
{
register struct sockaddr_iso *isock;
if ((isock = (struct sockaddr_iso *) calloc (1, sizeof *isock)) == NULL)
return NOTOK;
isock -> siso_family = AF_ISO;
isock -> siso_nlen = implode ((u_char *) isock -> siso_data, s,
strlen (s));
*x = isock;
return OK;
}
/* ARGSUSED */
static int clnpaddr_print (x, os)
struct sockaddr_iso *x;
OS os;
{
char buffer[sizeof x -> siso_data * 2 + 1];
buffer[explode (buffer, (u_char *) x -> siso_data, (int) x -> siso_nlen)] =
NULL;
printf ("NS+%s", buffer);
}
static add_clnpaddr ()
{
(void) add_syntax ("ClnpAddress", clnpaddr_encode, clnpaddr_decode,
clnpaddr_free, clnpaddr_parse, clnpaddr_print);
}
/* */
int readsyntax ()
{
add_integer ();
add_string ();
add_object ();
add_null ();
add_ipaddr ();
add_netaddr ();
add_counter ();
add_gauge ();
add_timeticks ();
add_clnpaddr ();
}
/* */
int add_syntax (name, f_encode, f_decode, f_free, f_parse, f_print)
char *name;
IFP f_encode,
f_decode,
f_free,
f_parse,
f_print;
{
int i;
register OS os = synlast++;
if ((i = synlast - syntaxes) >= MAXSYN)
return NOTOK;
bzero ((char *) os, sizeof *os);
os -> os_name = name;
os -> os_encode = f_encode;
os -> os_decode = f_decode;
os -> os_free = f_free;
os -> os_parse = f_parse;
os -> os_print = f_print;
return i;
}
/* */
OS text2syn (name)
char *name;
{
register OS os;
for (os = syntaxes; os < synlast; os++)
if (strcmp (os -> os_name, name) == 0)
return os;
return NULLOS;
}