BSD 4_3_Net_2 development
[unix-history] / usr / src / contrib / isode / snmp / snmpi.c
/* snmpi.c - really minimal SNMP initiator */
#ifndef lint
static char *rcsid = "$Header: /f/osi/snmp/RCS/snmpi.c,v 7.28 91/03/09 11:57:50 mrose Exp $";
#endif
/*
* $Header: /f/osi/snmp/RCS/snmpi.c,v 7.28 91/03/09 11:57:50 mrose Exp $
*
* 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: snmpi.c,v $
* Revision 7.28 91/03/09 11:57:50 mrose
* update
*
* Revision 7.27 91/02/22 09:44:34 mrose
* Interim 6.8
*
* Revision 7.26 91/01/11 15:35:28 mrose
* sets
*
* Revision 7.25 91/01/07 12:41:08 mrose
* update
*
* Revision 7.24 90/10/23 20:37:09 mrose
* update
*
* Revision 7.23 90/09/26 19:23:02 mrose
* new-mibs
*
* Revision 7.22 90/09/26 18:47:18 mrose
* more-compile
*
* Revision 7.21 90/09/26 14:57:48 mrose
* compile -f
*
* Revision 7.20 90/09/07 11:11:39 mrose
* update
*
* Revision 7.19 90/09/03 12:58:04 mrose
* update
*
* Revision 7.18 90/08/30 15:11:11 mrose
* ho-hum
*
* Revision 7.17 90/08/30 01:32:05 mrose
* update
*
* Revision 7.16 90/08/20 21:25:52 mrose
* touch-up
*
* Revision 7.15 90/08/16 17:01:13 mrose
* touch-up
*
* Revision 7.14 90/08/08 14:01:31 mrose
* stuff
*
* Revision 7.13 90/07/09 14:49:34 mrose
* sync
*
* Revision 7.12 90/06/23 18:25:14 mrose
* now
*
* Revision 7.11 90/06/23 17:01:55 mrose
* update
*
* Revision 7.10 90/05/12 17:02:09 mrose
* sync
*
* Revision 7.9 90/02/23 17:47:59 mrose
* update
*
* Revision 7.8 90/02/19 19:17:05 mrose
* again
*
* Revision 7.7 90/01/27 08:22:04 mrose
* touch-up
*
* Revision 7.6 90/01/11 18:34:43 mrose
* real-sync
*
* Revision 7.5 89/12/19 17:57:56 mrose
* touch-up
*
* Revision 7.4 89/12/19 16:18:26 mrose
* dgram
*
* Revision 7.3 89/12/12 16:13:47 mrose
* touch-up
*
* Revision 7.2 89/12/11 16:22:33 mrose
* more clts
*
* Revision 7.1 89/12/01 10:42:18 mrose
* clts
*
* Revision 7.0 89/11/23 22:23:30 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 <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <varargs.h>
#include "SNMP-types.h"
#include "objects.h"
#include <sys/ioctl.h>
#include "tailor.h"
#include "dgram.h"
#include "tsap.h"
#ifdef TCP
#include "internet.h"
#endif
#ifdef X25
#include "x25.h"
#define COTS
#endif
#ifdef TP4
#include "tp4.h"
#if !defined(CLTS) && !defined(COTS)
#define COTS
#endif
#endif
/* \f DATA */
int debug = 0;
static int verbose = 0;
int watch = 0;
static char *myname = "snmp";
static char **op = NULLVP;
static int ontty;
static int armed;
static jmp_buf intrenv;
static int interrupted;
static SFP istat;
SFD intrser ();
static char *defs = NULLCP;
static PS ps;
static char *community = "public";
static int sd;
static struct TSAPaddr snmp_ta;
char *snmp_error ();
struct type_SNMP_Message *new_message ();
void adios (), advise ();
/* \f */
struct dispatch {
char *ds_name; /* command name */
IFP ds_fnx; /* dispatch */
char *ds_help; /* help string */
};
struct dispatch *getds ();
int f_audit ();
#ifdef BSD42
int f_bulk ();
#endif
int f_compile (), f_dump ();
int f_get (), f_get_next (), f_set ();
int f_help (), f_quit (), f_status ();
static struct dispatch dispatches[] = {
"audit", f_audit, "audit traps",
#ifdef BSD42
"bulk", f_bulk, "bulk retrieve colums from a table",
#endif
"compile", f_compile, "write compiled objects file",
"dump", f_dump, "dump a portion of the MIB",
"get", f_get, "perform get operation",
"help", f_help, "print help information",
"next", f_get_next, "perform powerful get-next operation",
"quit", f_quit, "terminate program",
"set", f_set, "perform set operation",
"status", f_status, "report status",
NULL
};
static int helpwidth;
#ifndef SYS5
long random ();
#endif
long time ();
/* \f MAIN */
/* ARGSUSED */
main (argc, argv, envp)
int argc;
char **argv,
**envp;
{
int eof,
status,
vecp;
char buffer[BUFSIZ],
*vec[NVEC + 1];
arginit (argv);
status = 0;
if (op) {
vecp = 0;
while (*op)
vec[vecp++] = *op++;
vec[vecp] = NULL;
if (snmploop (vec, NOTOK) == NOTOK)
status = 1;
goto were_out_of_here;
}
istat = signal (SIGINT, intrser);
eof = 0;
for (interrupted = 0;; interrupted = 0) {
if (getline ("%s> ", buffer) == NOTOK) {
if (eof)
break;
eof = 1;
continue;
}
eof = 0;
bzero ((char *) vec, sizeof vec);
if ((vecp = str2vec (buffer, vec)) < 1)
continue;
switch (snmploop (vec, OK)) {
case NOTOK:
status = 1;
break;
case OK:
default:
continue;
case DONE:
status = 0;
break;
}
break;
}
(void) signal (SIGINT, istat);
were_out_of_here: ;
#ifdef COTS
if (snmp_ta.ta_addrs -> na_stack != NA_TCP) {
struct TSAPdisconnect tds;
#ifdef CLTS
if (snmp_ta.ta_addrs -> na_stack != NA_NSAP)
#endif
(void) TDiscRequest (sd, NULLCP, 0, &tds);
}
#endif
exit (status); /* NOTREACHED */
}
/* \f */
static int snmploop (vec, error)
char **vec;
int error;
{
register struct dispatch *ds;
if ((ds = getds (strcmp (*vec, "?") ? *vec : "help")) == NULL)
return error;
switch ((*ds -> ds_fnx) (vec)) {
case NOTOK:
return error;
case OK:
default:
return OK;
case DONE:
return DONE;
}
}
/* \f */
static struct dispatch *getds (name)
char *name;
{
register int longest,
nmatches;
register char *p,
*q;
char buffer[BUFSIZ];
register struct dispatch *ds,
*fs;
longest = nmatches = 0;
for (ds = dispatches; p = ds -> ds_name; ds++) {
for (q = name; *q == *p++; q++)
if (*q == NULL)
return ds;
if (*q == NULL)
if (q - name > longest) {
longest = q - name;
nmatches = 1;
fs = ds;
}
else
if (q - name == longest)
nmatches++;
}
switch (nmatches) {
case 0:
advise (NULLCP, "unknown operation \"%s\"", name);
return NULL;
case 1:
return fs;
default:
for (ds = dispatches, p = buffer; q = ds -> ds_name; ds++)
if (strncmp (q, name, longest) == 0) {
(void) sprintf (p, "%s \"%s\"", p != buffer ? "," : "", q);
p += strlen (p);
}
advise (NULLCP, "ambiguous operation, it could be one of:%s",
buffer);
return NULL;
}
}
/* \f OPERATIONS */
static int f_audit (vec)
char **vec;
{
int follow,
forever,
i;
long longtimeago,
now;
char *cp,
*file;
PE pe,
p;
PS ps2;
struct type_SNMP_Audit *au;
FILE *fp;
file = "snmp.traps";
if (*++vec != NULL && strcmp (*vec, "-help") == 0) {
printf ("audit [-f | -N | +N] [file]\n");
printf (" audit trap sink\n");
printf (" -f: endless loop\n");
printf (" -N: last N traps\n");
printf (" +N: first N traps\n");
printf (" file: trap file (default %s)\n", file);
return OK;
}
follow = forever = 0;
for (; cp = *vec; vec++)
switch (*cp) {
case '-':
if (strcmp (cp, "-f") == 0)
forever++, follow = 0;
else
follow = -atoi (++cp), forever = 0;
break;
case '+':
follow = atoi (++cp), forever = 0;
break;
default:
file = cp;
break;
}
file = _isodefile (isodelogpath, file);
if ((fp = fopen (file, "r")) == NULL) {
advise (file, "unable to read");
return OK;
}
pe = p = NULLPE, au = NULL;
if ((ps2 = ps_alloc (std_open)) == NULLPS) {
advise (NULLCP, "ps_alloc(std_open): you lose");
goto out;
}
if (std_setup (ps2, fp) == NOTOK) {
advise (NULLCP, "std_setup: %s", ps_error (ps2 -> ps_errno));
goto out;
}
(void) time (&now);
longtimeago = now - 6L * 30L * 24L * 60L * 60L;
if (follow < 0) {
register long offset,
*lp,
*ep;
long *opp;
follow = -follow;
if ((opp = (long *) calloc ((unsigned) follow, sizeof *opp)) == NULL)
adios (NULLCP, "out of memory");
offset = ftell (fp);
for (ep = (lp = opp) + follow; lp < ep; lp++)
*lp = offset;
lp = opp;
for (;;) {
if ((pe = ps2pe (ps2)) == NULLPE)
break;
if (decode_SNMP_Audit (pe, 1, NULLIP, NULLVP, &au) == NOTOK)
goto bad_audit;
fseek (fp, (long) au -> sizeOfEncodingWhichFollows, 1);
free_SNMP_Audit (au);
*lp++ = offset;
if (lp >= ep)
lp = opp;
offset = ftell (fp);
}
fseek (fp, *lp, 0);
free ((char *) opp);
follow = 0;
}
for (i = 1;; i++) {
long mtime;
UTC ut;
if (follow > 0 && i > follow)
break;
if ((pe = ps2pe (ps2)) == NULLPE) {
if (ps2 -> ps_errno)
advise (NULLCP, "ps2pe: %s", ps_error (ps2 -> ps_errno));
else
if (forever) {
clearerr (fp);
ps2 -> ps_errno = PS_ERR_NONE;
sleep (1);
continue;
}
break;
}
if (decode_SNMP_Audit (pe, 1, NULLIP, NULLVP, &au) == NOTOK) {
bad_audit: ;
advise (NULLCP, "decode_SNMP_Audit: %s", PY_pepy);
break;
}
if ((cp = qb2str (au -> dateAndTime)) == NULL) {
no_mem: ;
advise (NULLCP, "qb2str: out of memory");
break;
}
ut = str2gent (cp, strlen (cp));
free (cp);
if (ut == NULL) {
advise (NULLCP, "str2gent: you lose");
break;
}
mtime = gtime (ut2tm (ut));
cp = ctime (&mtime);
if (forever)
(void) time (&now);
if (mtime < longtimeago || mtime > now)
printf ("%-7.7s %-4.4s ", cp + 4, cp + 20);
else
printf ("%-12.12s ", cp + 4);
if ((cp = qb2str (au -> source)) == NULL)
goto no_mem;
printf ("%s\n", cp);
free (cp);
if ((p = ps2pe (ps2)) == NULLPE) {
if (ps2 -> ps_errno)
advise (NULLCP, "ps2pe: %s", ps_error (ps2 -> ps_errno));
break;
}
if (print_SNMP_Message (p, 1, NULLIP, NULLVP, NULLCP) == NOTOK)
printf ("\n");
free_SNMP_Audit (au), au = NULL;
}
out: ;
(void) fclose (fp);
if (ps2)
ps_free (ps2);
if (pe)
pe_free (pe);
if (p)
pe_free (p);
if (au)
free_SNMP_Audit (au);
return OK;
}
/* \f */
#ifdef BSD42
int bulk1 (), bulk2 ();
static int f_bulk (vec)
char **vec;
{
int result;
IFP fnx = bulk1;
register struct type_SNMP_VarBindList **vp;
struct type_SNMP_VarBindList *vb;
OT et = NULL;
if (*++vec != NULL && strcmp (*vec, "-help") == 0) {
printf ("bulk [-alg1 | -alg2] columns...\n");
printf (" with arguments, bulk retrieves columns from a table\n");
return OK;
}
while (*vec) {
if (strcmp (*vec, "-alg1") == 0) {
fnx = bulk1;
vec++;
continue;
}
if (strcmp (*vec, "-alg2") == 0) {
fnx = bulk2;
vec++;
continue;
}
break;
}
if (*vec == NULL)
return OK;
#ifdef COTS
if (snmp_ta.ta_addrs -> na_stack != NA_TCP) {
#ifdef CLTS
if (snmp_ta.ta_addrs -> na_stack != NA_NSAP) {
#endif
advise (NULLCP, "bulk requires CL-mode transport!");
return NOTOK;
#ifdef CLTS
}
#endif
}
#endif
vp = &vb, vb = NULL;
for (result = NOTOK; *vec; vec++) {
register struct type_SNMP_VarBindList *bind;
register struct type_SNMP_VarBind *v;
OT ot;
if ((ot = text2obj (*vec)) == NULL) {
advise (NULLCP, "unknown object \"%s\"", *vec);
goto out;
}
if (et) {
register OID eid = et -> ot_name,
oid = ot -> ot_name;
if (eid -> oid_nelem != oid -> oid_nelem - 1
|| bcmp ((char *) eid -> oid_elements,
(char *) oid -> oid_elements,
eid -> oid_nelem
* sizeof (eid -> oid_elements[0])) != 0) {
advise (NULLCP, "%s not in same table as previous arguments",
ot -> ot_text);
goto out;
}
}
else {
/* int i; */
ot -> ot_name -> oid_nelem--;
et = name2obj (ot -> ot_name);
ot -> ot_name -> oid_nelem++;
if (et == NULL) {
advise (NULLCP, "unable to find row object for %s",
ot -> ot_text);
goto out;
}
if (et -> ot_syntax
/* || (i = strlen (et -> ot_text)) <= 5
|| strcmp (et -> ot_text + i - 5, "Entry")*/) {
advise (NULLCP, "%s is not a column object", ot -> ot_text);
goto out;
}
}
if ((bind = (struct type_SNMP_VarBindList *) calloc (1, sizeof *bind))
== NULL)
adios (NULLCP, "out of memory");
*vp = bind, vp = &bind -> next;
if ((v = (struct type_SNMP_VarBind *) calloc (1, sizeof *v)) == NULL)
adios (NULLCP, "out of memory");
bind -> VarBind = v;
if ((v -> name = oid_cpy (ot -> ot_name)) == NULLOID
|| (v -> value = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM,
PE_PRIM_NULL)) == NULLPE)
adios (NULLCP, "out of memory");
}
(*fnx) (ps, sd, vb, community);
result = OK;
out: ;
free_SNMP_VarBindList (vb);
return result;
}
#endif
/* \f */
static char *access_t[] = { "not-accessible",
"read-only",
"write-only",
"read-write"};
static char *status_t[] = { "obsolete",
"mandatory",
"optional",
"deprecated" };
static int f_compile (vec)
char **vec;
{
register int i;
int fast;
char *cp,
*file;
register OS os;
register OT ot;
FILE *fp;
fast = 0;
file = defs ? defs : "./objects.defs";
if (*++vec != NULL && strcmp (*vec, "-help") == 0) {
printf ("compile [-f] [file]\n");
printf (" -f: brief output (default to stdout)\n");
printf (" file: output file (default %s)\n", file);
return OK;
}
while (cp = *vec++) {
if (strcmp (cp, "-f") == 0) {
fast = 1, file = NULLCP;
continue;
}
file = cp;
}
if (file) {
if ((fp = fopen (file, "w")) == NULL) {
advise (file, "unable to write");
return OK;
}
if (!fast) {
register int j,
k;
i = j = k = 0;
for (ot = text2obj ("ccitt"); ot; ot = ot -> ot_next) {
i++;
j += strlen (ot -> ot_text)
+ strlen (sprintoid (ot -> ot_name));
k += ot -> ot_name -> oid_nelem;
}
j += i << 1, k += i;
fprintf (fp, "--* compiled %d %d %d\n", i, j, k);
}
}
else
fp = stdout;
for (ot = text2obj ("ccitt"); ot; ot = ot -> ot_next) {
if (fast) {
fprintf (fp, "%s=%s\n", ot -> ot_text, sprintoid (ot -> ot_name));
continue;
}
fprintf (fp, "%-20s %-20s", ot -> ot_text, sprintoid (ot -> ot_name));
if ((os = ot -> ot_syntax) || ot -> ot_status)
fprintf (fp, " %-15s %-15s %s",
os ? os -> os_name : "Aggregate",
access_t[ot -> ot_access & OT_RDWRITE],
status_t[ot -> ot_status & OT_DEPRECATED]);
fprintf (fp, "\n");
}
if (file)
(void) fclose (fp);
if (!fast)
advise (NULLCP, "%d objects written to %s", i, file);
return OK;
}
/* \f */
static int f_dump (vec)
char **vec;
{
int request_id,
rows,
timing = 0;
char *nvec[3];
OID oid;
PE pe;
struct type_SNMP_Message *msg;
register struct type_SNMP_PDU *parm;
register struct type_SNMP_VarBindList *vp;
struct timeval tvs,
now;
if (*++vec != NULL && strcmp (*vec, "-help") == 0) {
printf ("dump [object]\n");
printf (" with no arguments, dump entire MIB\n");
printf (" with an argument, dump a portion of the MIB\n");
return OK;
}
if (*vec && strcmp (*vec, "-time") == 0) {
timing++;
(void) gettimeofday (&tvs, (struct timezone *) 0);
vec++;
}
nvec[0] = "dump";
nvec[1] = *vec ? *vec : "0.0";
nvec[2] = NULL;
if ((msg = new_message (type_SNMP_PDUs_get__next__request, nvec)) == NULL)
return OK;
request_id = msg -> data -> un.get__response -> request__id = 0;
if (*vec) {
if ((oid = oid_cpy (msg -> data -> un.get__next__request ->
variable__bindings -> VarBind -> name)) == NULLOID)
adios (NULLCP, "out of memory");
}
else
oid = NULLOID;
rows = 0;
again: ;
pe = NULLPE;
if (encode_SNMP_Message (&pe, 1, 0, NULLCP, msg) != NOTOK) {
if (watch)
(void) print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP);
if (pe2ps (ps, pe) == NOTOK) {
advise (NULLCP, "pe2ps: %s", ps_error (ps -> ps_errno));
goto out;
}
}
else
advise (NULLCP, "encode_SNMP_Message: %s", PY_pepy);
try_again: ;
if (pe)
pe_free (pe);
pe = NULLPE;
free_SNMP_Message (msg);
msg = NULL;
if ((pe = ps2pe (ps)) == NULLPE) {
advise (NULLCP, "ps2pe: %s", ps_error (ps -> ps_errno));
goto out;
}
if (decode_SNMP_Message (pe, 1, NULLIP, NULLVP, &msg) == NOTOK) {
advise (NULLCP, "decode_SNMP_Message: %s", PY_pepy);
goto out;
}
if (watch)
(void) print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP);
if (msg -> data -> offset != type_SNMP_PDUs_get__response) {
advise (NULLCP, "unexpected message type %d",
msg -> data -> offset);
goto out;
}
if ((parm = msg -> data -> un.get__response) -> request__id
!= request_id) {
fprintf (stderr, "request-id mismatch (got %d, wanted %d)\n",
parm -> request__id, request_id);
goto try_again;
}
if (parm -> error__status != int_SNMP_error__status_noError) {
if (parm -> error__status != int_SNMP_error__status_noSuchName)
fprintf (stderr, "%s at position %d\n",
snmp_error (parm -> error__status), parm -> error__index);
goto out;
}
for (vp = parm -> variable__bindings; vp; vp = vp -> next) {
caddr_t value;
register OI oi;
register OS os;
register struct type_SNMP_VarBind *v = vp -> VarBind;
if (oid
&& (oid -> oid_nelem > v -> name -> oid_nelem
|| bcmp ((char *) oid -> oid_elements,
(char *) v -> name -> oid_elements,
oid -> oid_nelem
* sizeof oid -> oid_elements[0])))
goto out;
if (timing)
continue;
printf ("%s=", oid2ode (vp -> VarBind -> name));
if ((oi = name2inst (v -> name)) == NULL
|| (os = oi -> oi_type -> ot_syntax) == NULL
|| (*os -> os_decode) (&value, v -> value) == NOTOK)
vunknown (v -> value);
else {
(*os -> os_print) (value, os);
printf ("\n");
(*os -> os_free) (value);
}
}
rows++;
if (pe)
pe_free (pe);
msg -> data -> offset = type_SNMP_PDUs_get__next__request;
request_id = ++parm -> request__id;
goto again;
out: ;
if (oid)
oid_free (oid);
if (pe)
pe_free (pe);
if (msg)
free_SNMP_Message (msg);
if (timing) {
(void) gettimeofday (&now, (struct timezone *) 0);
now.tv_sec -= tvs.tv_sec;
if ((now.tv_usec -= tvs.tv_usec) < 0)
now.tv_sec--, now.tv_usec += 1000000;
advise (NULLCP,
"%d entr%s retrieved in %d.%06d seconds",
rows, rows != 1 ? "ies" : "y", now.tv_sec, now.tv_usec);
}
return OK;
}
/* \f */
static int f_get (vec)
char **vec;
{
(void) process (new_message (type_SNMP_PDUs_get__request, vec));
}
/* \f */
static int f_get_next (vec)
char **vec;
{
(void) process (new_message (type_SNMP_PDUs_get__next__request, vec));
}
/* \f */
static int f_set (vec)
char **vec;
{
(void) process (new_message (type_SNMP_PDUs_set__request, vec));
}
/* \f */
static char *errors[] = {
"noError", "tooBig", "noSuchName", "badValue", "readOnly", "genErr"
};
char *snmp_error (i)
integer i;
{
static char buffer[BUFSIZ];
if (0 < i && i < sizeof errors / sizeof errors[0])
return errors[i];
(void) sprintf (buffer, "error %d", i);
return buffer;
}
/* \f */
static struct type_SNMP_Message *new_message (offset, vec)
int offset;
char **vec;
{
register struct type_SNMP_Message *msg;
register struct type_SNMP_PDUs *pdu;
register struct type_SNMP_PDU *parm;
register struct type_SNMP_VarBindList **vp;
if ((msg = (struct type_SNMP_Message *) calloc (1, sizeof *msg)) == NULL)
adios (NULLCP, "out of memory");
msg -> version = int_SNMP_version_version__1;
if ((msg -> community = str2qb (community, strlen (community), 1)) == NULL)
adios (NULLCP, "out of memory");
if ((pdu = (struct type_SNMP_PDUs *) calloc (1, sizeof *pdu)) == NULL)
adios (NULLCP, "out of memory");
msg -> data = pdu;
pdu -> offset = offset;
/* for now, always a PDU... */
if ((parm = (struct type_SNMP_PDU *) calloc (1, sizeof *parm)) == NULL)
adios (NULLCP, "out of memory");
pdu -> un.get__request = parm;
#ifndef SYS5
parm -> request__id = ((int) random ()) & 0x7fffffff;
#else
parm -> request__id = ((int) rand ()) & 0x7fffffff;
#endif
vp = &parm -> variable__bindings;
for (vec++; *vec; vec++) {
register struct type_SNMP_VarBindList *bind;
register struct type_SNMP_VarBind *v;
if ((bind = (struct type_SNMP_VarBindList *) calloc (1, sizeof *bind))
== NULL)
adios (NULLCP, "out of memory");
*vp = bind, vp = &bind -> next;
if ((v = (struct type_SNMP_VarBind *) calloc (1, sizeof *v)) == NULL)
adios (NULLCP, "out of memory");
bind -> VarBind = v;
if (get_ava (v, *vec, offset) == NOTOK) {
free_SNMP_Message (msg);
return NULL;
}
}
return msg;
}
/* \f */
static int get_ava (v, ava, offset)
register struct type_SNMP_VarBind *v;
char *ava;
int offset;
{
int result;
caddr_t value;
register char *cp;
register OI oi;
register OT ot;
register OS os;
OID oid;
if (cp = index (ava, '=')) {
if (offset != type_SNMP_PDUs_set__request)
advise (NULLCP, "value unnecessary for get operation");
*cp++ = NULL;
}
else
if (offset == type_SNMP_PDUs_set__request) {
advise (NULLCP, "need variable=value for set operation");
return NOTOK;
}
if ((oi = text2inst (ava)) == NULL) {
if (cp || (oid = text2oid (ava)) == NULL) {
advise (NULLCP, "unknown variable \"%s\"", ava);
return NOTOK;
}
ot = NULLOT;
}
else
ot = oi -> oi_type;
if ((v -> name = oid_cpy (oi ? oi -> oi_name : oid)) == NULLOID)
adios (NULLCP, "out of memory");
if (cp == NULL) {
if ((v -> value = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_NULL))
== NULLPE)
adios (NULLCP, "out of memory");
}
else {
if ((os = ot -> ot_syntax) == NULL) {
advise (NULLCP, "no syntax defined for object \"%s\"", ava);
return NOTOK;
}
if ((*os -> os_parse) (&value, cp) == NOTOK) {
advise (NULLCP, "invalid value for variable \"%s\": \"%s\"",
ava, cp);
return NOTOK;
}
result = (*os -> os_encode) (value, &v -> value);
(*os -> os_free) (value);
if (result == NOTOK) {
advise (NULLCP, "encoding error for variable \"%s\"", ava);
return NOTOK;
}
}
if (oi == NULL)
oid_free (oid);
return OK;
}
/* \f */
static int process (msg)
struct type_SNMP_Message *msg;
{
int request_id;
PE pe;
register struct type_SNMP_PDU *parm;
register struct type_SNMP_VarBindList *vp;
if (msg == NULL)
return OK;
request_id = msg -> data -> un.get__request -> request__id;
if (encode_SNMP_Message (&pe, 1, 0, NULLCP, msg) != NOTOK) {
if (watch)
(void) print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP);
if (pe2ps (ps, pe) == NOTOK) {
advise (NULLCP, "pe2ps: %s", ps_error (ps -> ps_errno));
goto out;
}
}
else
advise (NULLCP, "encode_SNMP_Message: %s", PY_pepy);
try_again: ;
if (pe)
pe_free (pe);
pe = NULLPE;
free_SNMP_Message (msg);
msg = NULL;
if ((pe = ps2pe (ps)) == NULLPE) {
advise (NULLCP, "ps2pe: %s", ps_error (ps -> ps_errno));
goto out;
}
if (decode_SNMP_Message (pe, 1, NULLIP, NULLVP, &msg) == NOTOK) {
advise (NULLCP, "decode_SNMP_Message: %s", PY_pepy);
goto out;
}
if (watch)
(void) print_SNMP_Message (pe, 1, NULLIP, NULLVP, NULLCP);
if (msg -> data -> offset != type_SNMP_PDUs_get__response) {
advise (NULLCP, "unexpected message type %d",
msg -> data -> offset);
goto out;
}
if ((parm = msg -> data -> un.get__response) -> request__id
!= request_id) {
fprintf (stderr, "request-id mismatch (got %d, wanted %d)\n",
parm -> request__id, request_id);
goto try_again;
}
if (parm -> error__status != int_SNMP_error__status_noError) {
fprintf (stderr, "%s at position %d\n",
snmp_error (parm -> error__status), parm -> error__index);
goto out;
}
for (vp = parm -> variable__bindings; vp; vp = vp -> next) {
caddr_t value;
register OI oi;
register OS os;
register struct type_SNMP_VarBind *v = vp -> VarBind;
if ((oi = name2inst (v -> name)) == NULL) {
advise (NULLCP, "unknown variable \"%s\"", oid2ode (v -> name));
no_dice: ;
printf ("%s=", oid2ode (v -> name));
vunknown (v -> value);
continue;
}
if ((os = oi -> oi_type -> ot_syntax) == NULL) {
advise (NULLCP, "unknown syntax for object \"%s\"",
oi -> oi_type -> ot_text);
goto no_dice;
}
if ((*os -> os_decode) (&value, v -> value) == NOTOK) {
advise (NULLCP, "decode error for variable \"%s\"",
oid2ode (v -> name));
goto no_dice;
}
printf ("%s=", oid2ode (v -> name));
(*os -> os_print) (value, os);
printf ("\n");
(*os -> os_free) (value);
}
out: ;
if (pe)
pe_free (pe);
if (msg)
free_SNMP_Message (msg);
return OK;
}
/* \f */
static int f_help (vec)
char **vec;
{
register int i,
j,
w;
int columns,
width,
lines;
register struct dispatch *ds,
*es;
for (es = dispatches; es -> ds_name; es++)
continue;
width = helpwidth;
if (*++vec == NULL) {
if ((columns = ncols (stdout) / (width = (width + 8) & ~7)) == 0)
columns = 1;
lines = ((es - dispatches) + columns - 1) / columns;
printf ("Operations:\n");
for (i = 0; i < lines; i++)
for (j = 0; j < columns; j++) {
ds = dispatches + j * lines + i;
printf ("%s", ds -> ds_name);
if (ds + lines >= es) {
printf ("\n");
break;
}
for (w = strlen (ds -> ds_name); w < width; w = (w + 8) & ~7)
(void) putchar ('\t');
}
printf ("\n");
return OK;
}
if (strcmp (*vec, "-help") == 0) {
printf ("help [commands ...]\n");
printf (" with no arguments, lists operations which may be invoked\n");
printf (" otherwise prints help for each operation given\n");
return OK;
}
for (; *vec; vec++)
if (strcmp (*vec, "?") == 0) {
for (ds = dispatches; ds -> ds_name; ds++)
printf ("%-*s\t- %s\n", width, ds -> ds_name, ds -> ds_help);
break;
}
else
if (ds = getds (*vec))
printf ("%-*s\t- %s\n", width, ds -> ds_name, ds -> ds_help);
return OK;
}
/* \f */
static int f_quit (vec)
char **vec;
{
if (vec && *++vec != NULL && strcmp (*vec, "-help") == 0) {
printf ("quit\n");
printf (" terminate fred\n");
return OK;
}
return DONE;
}
/* \f */
static int f_status (vec)
char **vec;
{
if (*++vec != NULL && strcmp (*vec, "-help") == 0) {
printf ("status\n");
printf (" report status\n");
return OK;
}
printf ("Connected to %s using community \"%s\"\n",
taddr2str (&snmp_ta), community);
return OK;
}
/* \f SYNTAX */
static char *ifType[] = {
"other", "regular1822", "hdh1822", "ddn-x25", "rfc877-x25",
"ethernet-csmacd", "iso88023-csmacd", "iso88024-tokenBus",
"iso88025-tokenRing", "iso88026-man", "starLan", "proteon-10Mbit",
"proteon-80Mbit", "hyperchannel", "fddi", "lapb", "sdlc", "t1-carrier",
"cept", "basicISDN", "primaryISDN", "propPointToPointSerial",
"ppp", "softwareLoopback", "eon", "ethernet-3Mbit",
"nsip", "slip"
};
static char *ifStatus[] = {
"up", "down", "testing"
};
static char *ipForwarding[] = {
"gateway", "host"
};
static char *routeType[] = {
"other", "invalid", "direct", "remote"
};
static char *ipRouteProto[] = {
"other", "local", "netmgmt", "icmp", "egp", "ggp", "hello", "rip", "is-is",
"es-is", "ciscoIgrp", "bbnSpfIgp", "ospf", "bgp"
};
static char *netToMediaType[] = {
"other", "invalid", "dynamic", "static"
};
static char *tcpRtoAlgorithm[] = {
"other", "constant", "rsre", "vanj"
};
static char *tcpConnState[] = {
"closed", "listen", "synSent", "synReceived", "established", "finWait1",
"finWait2", "closeWait", "lastAck", "closing", "timewait"
};
static char *egpNeighState[] = {
"idle", "acquisition", "down", "up", "cease"
};
static char *egpNeighMode[] = {
"active", "passive"
};
static char *egpNeighEventTrigger[] = {
"start", "stop"
};
static char *enabled[] = {
"enabled", "disabled"
};
static char *status[] = {
"valid", "invalid"
};
static char *smuxPstatus[] = {
"valid", "invalid", "connecting"
};
static struct ivar {
char *iv_object;
char **iv_values;
int iv_nvalue;
} ivars[] = {
"ifType", ifType,
sizeof ifType / sizeof ifType[0],
"ifAdminStatus", ifStatus,
sizeof ifStatus / sizeof ifStatus[0],
"ifOperStatus", ifStatus,
sizeof ifStatus / sizeof ifStatus[0],
"ipForwarding", ipForwarding,
sizeof ipForwarding / sizeof ipForwarding[0],
"ipRouteType", routeType,
sizeof routeType / sizeof routeType[0],
"ipRouteProto", ipRouteProto,
sizeof ipRouteProto / sizeof ipRouteProto[0],
"ipNetToMediaType", netToMediaType,
sizeof netToMediaType / sizeof netToMediaType[0],
"tcpRtoAlgorithm", tcpRtoAlgorithm,
sizeof tcpRtoAlgorithm / sizeof tcpRtoAlgorithm[0],
"tcpConnState", tcpConnState,
sizeof tcpConnState / sizeof tcpConnState[0],
"egpNeighState", egpNeighState,
sizeof egpNeighState / sizeof egpNeighState[0],
"egpNeighMode", egpNeighMode,
sizeof egpNeighMode / sizeof egpNeighMode[0],
"egpNeighEventTrigger", egpNeighEventTrigger,
sizeof egpNeighEventTrigger / sizeof egpNeighEventTrigger[0],
"snmpEnableAuthenTraps", enabled,
sizeof enabled / sizeof enabled[0],
"smuxPstatus", smuxPstatus,
sizeof smuxPstatus / sizeof smuxPstatus[0],
"smuxTstatus", status,
sizeof status / sizeof status[0],
"unixNetstat", enabled,
sizeof enabled / sizeof enabled[0],
NULL
};
/* \f */
static int enum_print (x, os)
integer *x;
OS os;
{
int i = *x;
if (i <= 0 || i > os -> os_data2)
printf ("unknown(%d)", i);
else
printf ("%s(%d)", os -> os_data1[i - 1], i);
}
static moresyntax () {
register struct ivar *iv;
register OT ot;
register OS os;
for (iv = ivars; iv -> iv_object; iv++)
if (ot = text2obj (iv -> iv_object)) {
char *name;
if ((os = ot -> ot_syntax) == NULL) {
advise (NULLCP, "no syntax defined for object \"%s\"",
iv -> iv_object);
continue;
}
name = os -> os_name;
(void) add_syntax (iv -> iv_object, os -> os_encode,
os -> os_decode, os -> os_free, os -> os_parse,
enum_print);
if ((os = text2syn (iv -> iv_object)) == NULL)
adios (NULLCP, "lost syntax for object \"%s\"",
iv -> iv_object);
ot -> ot_syntax = os;
os -> os_name = name;
os -> os_data1 = iv -> iv_values;
os -> os_data2 = iv -> iv_nvalue;
}
else
advise (NULLCP, "no \"%s\" object", iv -> iv_object);
}
/* \f MISCELLANY */
static arginit (vec)
char **vec;
{
int w;
register char *ap,
*pp;
register struct dispatch *ds;
#ifdef TCP
int port;
struct sockaddr_in in_socket;
register struct sockaddr_in *isock = &in_socket;
register struct hostent *hp;
register struct servent *sp;
#endif
register struct TSAPaddr *ta = &snmp_ta,
*tz;
register struct NSAPaddr *na = ta -> ta_addrs;
if (myname = rindex (*vec, '/'))
myname++;
if (myname == NULL || *myname == NULL)
myname = *vec;
isodetailor (myname, 1);
if (ontty = isatty (fileno (stdin)))
verbose++;
if ((sp = getservbyname ("snmp", "udp")) == NULL)
advise (NULLCP, "udp/snmp: unknown service");
bzero ((char *) ta, sizeof *ta);
#ifdef TCP
na -> na_stack = NA_TCP;
na -> na_community = ts_comm_tcp_default;
(void) strncpy (na -> na_domain, getlocalhost (),
sizeof na -> na_domain - 1);
na -> na_port = sp ? sp -> s_port : htons ((u_short) 161);
na -> na_tset = NA_TSET_UDP;
ta -> ta_naddr = 1;
#endif
for (vec++; ap = *vec; vec++) {
if (*ap == '-') {
while (*++ap)
switch (*ap) {
case 'a': /* e.g., NS+0504030201 */
if ((pp = *++vec) == NULL || *pp == '-')
adios (NULLCP, "usage: %s -a agent", myname);
#ifdef TCP
if (hp = gethostbystring (pp)) {
if (na -> na_stack != NA_TCP)
adios (NULLCP, "use -a at most once...");
inaddr_copy (hp, isock);
(void) strncpy (na -> na_domain,
inet_ntoa (isock -> sin_addr),
sizeof na -> na_domain - 1);
}
else
#endif
if ((tz = str2taddr (pp)) && tz -> ta_naddr > 0) {
*ta = *tz; /* struct copy */
if (na -> na_stack == NA_TCP) {
if (na -> na_port == 0)
na -> na_port = sp ? sp -> s_port
: htons ((u_short) 161);
na -> na_tset = NA_TSET_UDP;
}
}
else
adios (NULLCP, "%s: unknown host", pp);
break;
#ifdef TCP
case 'p':
if ((pp = *++vec) == NULL
|| *pp == '-'
|| (port = atoi (pp)) <= 0)
adios (NULLCP, "usage: %s -p portno", myname);
if (na -> na_stack != NA_TCP)
adios (NULLCP, "-p not allowed with %s",
taddr2str (ta));
na -> na_port = htons ((u_short) port);
break;
#endif
case 'c':
if ((pp = *++vec) == NULL || *pp == '-')
adios (NULLCP, "usage: %s -c community", myname);
community = pp;
break;
case 'd':
debug++;
break;
case 'v':
verbose++;
break;
case 'w':
watch++;
break;
case 'f':
if ((pp = *++vec) == NULL || *pp == '-')
adios (NULLCP, "usage: %s -f file", myname);
defs = pp;
break;
default:
adios (NULLCP, "unknown switch -%c", *ap);
}
continue;
}
if (op == NULL) {
op = vec;
break;
}
}
helpwidth = 0;
for (ds = dispatches; ds -> ds_name; ds++)
if ((w = strlen (ds -> ds_name)) > helpwidth)
helpwidth = w;
if (ta -> ta_naddr == 0)
adios (NULLCP, "usage: %s -a string", myname);
switch (na -> na_stack) {
case NA_TCP:
#ifdef TCP
{
struct sockaddr_in lo_socket;
register struct sockaddr_in *lsock = &lo_socket;
bzero ((char *) lsock, sizeof *lsock);
if ((hp = gethostbystring (pp = getlocalhost ())) == NULL)
adios (NULLCP, "%s: unknown host", pp);
lsock -> sin_family = hp -> h_addrtype;
inaddr_copy (hp, lsock);
/* If the request is being sent out on the loopback interface,
make sure it appears to have originated from the loopback
interface, rather than the interface used as the default
hostname. If the interface used as the default hostname
is a serial link, responses to requests with this origin
may be undeliverable. (EJP) */
#define LOOPBACK ((127 << 24) + 1)
if (isock -> sin_addr.s_addr == LOOPBACK)
lsock -> sin_addr.s_addr = LOOPBACK;
#undef LOOPBACK
if ((sd = start_udp_client (lsock, 0, 0, 0)) == NOTOK)
adios ("failed", "start_udp_client");
bzero ((char *) isock, sizeof *isock);
if ((hp = gethostbystring (na -> na_domain)) == NULL)
adios (NULLCP, "%s: unknown host", na -> na_domain);
isock -> sin_family = hp -> h_addrtype;
isock -> sin_port = na -> na_port;
inaddr_copy (hp, isock);
if (join_udp_server (sd, isock) == NOTOK)
adios ("failed", "join_udp_server");
if ((ps = ps_alloc (dg_open)) == NULLPS
|| dg_setup (ps, sd, MAXDGRAM, read_udp_socket,
write_udp_socket, check_udp_socket)
== NOTOK) {
if (ps == NULLPS)
adios (NULLCP, "ps_alloc: out of memory");
else
adios (NULLCP, "dg_setup: %s",
ps_error (ps -> ps_errno));
}
}
break;
#else
adios (NULLCP, "UDP support not configured");
#endif
case NA_X25:
#ifdef X25
goto cots;
#else
adios (NULLCP, "X.25 support not configured");
#endif
case NA_NSAP:
#ifdef CLTS
{
union sockaddr_osi lo_socket;
register union sockaddr_osi *lsock = &lo_socket;
bzero ((char *) lsock, sizeof *lsock);
if ((sd = start_clts_client (lsock, 0, 0, 0)) == NOTOK)
adios ("failed", "start_clts_client");
(void) gen2tp4 (ta, lsock);
if (join_clts_server (sd, lsock) == NOTOK)
adios ("failed", "join_udp_server");
if ((ps = ps_alloc (dg_open)) == NULLPS
|| dg_setup (ps, sd, MAXDGRAM, read_clts_socket,
write_clts_socket, check_clts_socket)
== NOTOK) {
if (ps == NULLPS)
adios (NULLCP, "ps_alloc: out of memory");
else
adios (NULLCP, "dg_setup: %s",
ps_error (ps -> ps_errno));
}
}
break;
#else
#ifdef TP4
goto cots;
#else
adios (NULLCP, "TP4 support not configured");
#endif
#endif
default:
adios (NULLCP, "unknown network type 0x%x", na -> na_stack);
/* NOT REACHED */
#ifdef COTS
cots: ;
{
struct TSAPconnect tcs;
register struct TSAPconnect *tc = &tcs;
struct TSAPdisconnect tds;
register struct TSAPdisconnect *td = &tds;
if (verbose) {
fprintf (stderr, "%s... ", taddr2str (ta));
(void) fflush (stderr);
}
if (TConnRequest (NULLTA, ta, 0, NULLCP, 0, NULLQOS, tc, td)
== NOTOK) {
if (verbose)
fprintf (stderr," failed\n");
adios (NULLCP, td -> td_cc > 0
? "T-CONNECT.REQUEST: [%s] %*.*s"
: "T-CONNECT.REQUEST: [%s]",
TErrString (td -> td_reason),
td -> td_cc, td -> td_cc, td -> td_data);
}
fprintf (stderr, "connected\n");
if ((ps = ps_alloc (dg_open)) == NULLPS
|| dg_setup (ps, sd = tc -> tc_sd, MAXDGRAM, ts_read,
ts_write, NULLIFP) == NOTOK) {
if (ps == NULLPS)
adios (NULLCP, "ps_alloc: out of memory");
else
adios (NULLCP, "dg_setup: %s",
ps_error (ps -> ps_errno));
}
}
break;
#endif
}
#ifdef SYS5
(void) srand ((unsigned int) time ((long *) 0));
#else
(void) srandom ((int) time ((long *) 0));
#endif
ps_len_strategy = PS_LEN_LONG;
if (readobjects (defs) == NOTOK)
adios (NULLCP, "readobjects: %s", PY_pepy);
moresyntax ();
}
/* \f INTERACTIVE */
static int getline (prompt, buffer)
char *prompt,
*buffer;
{
register int i;
register char *cp,
*ep;
static int sticky = 0;
if (interrupted) {
interrupted = 0;
return NOTOK;
}
if (sticky) {
sticky = 0;
return NOTOK;
}
switch (setjmp (intrenv)) {
case OK:
armed++;
break;
case NOTOK:
if (ontty)
printf ("\n"); /* and fall */
default:
armed = 0;
return NOTOK;
}
if (ontty) {
printf (prompt, myname);
(void) fflush (stdout);
}
for (ep = (cp = buffer) + BUFSIZ - 1; (i = getchar ()) != '\n';) {
if (i == EOF) {
if (ontty)
printf ("\n");
clearerr (stdin);
if (cp == buffer)
longjmp (intrenv, DONE);
sticky++;
break;
}
if (cp < ep)
*cp++ = i;
}
*cp = NULL;
armed = 0;
return OK;
}
/* \f */
/* ARGSUSED */
static SFD intrser (sig)
int sig;
{
#ifndef BSDSIGS
(void) signal (SIGINT, intrser);
#endif
if (armed)
longjmp (intrenv, NOTOK);
interrupted++;
}
/* \f */
#ifndef TIOCGWINSZ
/* ARGSUSED */
#endif
static int ncols (fp)
FILE *fp;
{
#ifdef TIOCGWINSZ
int i;
struct winsize ws;
if (ioctl (fileno (fp), TIOCGWINSZ, (char *) &ws) != NOTOK
&& (i = ws.ws_col) > 0)
return i;
#endif
return 80;
}
/* \f ERRORS */
#ifndef lint
void _advise ();
void adios (va_alist)
va_dcl
{
va_list ap;
va_start (ap);
_advise (ap);
va_end (ap);
_exit (1);
}
#else
/* VARARGS */
void adios (what, fmt)
char *what,
*fmt;
{
adios (what, fmt);
}
#endif
#ifndef lint
void advise (va_alist)
va_dcl
{
va_list ap;
va_start (ap);
_advise (ap);
va_end (ap);
}
static void _advise (ap)
va_list ap;
{
char buffer[BUFSIZ];
asprintf (buffer, ap);
(void) fflush (stdout);
fprintf (stderr, "%s: ", myname);
(void) fputs (buffer, stderr);
(void) fputc ('\n', stderr);
(void) fflush (stderr);
}
#else
/* VARARGS */
void advise (what, fmt)
char *what,
*fmt;
{
advise (what, fmt);
}
#endif