1
0
Files
2022-09-29 17:59:04 +03:00

723 lines
14 KiB
C++

/*
* Copyright 1990 Silicon Graphics, Inc. All rights reserved.
*
* PDU Definitions
*
* $Revision: 1.7 $
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
#include <stdio.h>
#include <libc.h>
#include <string.h>
#include "oid.h"
#include "asn1.h"
#include "snmp.h"
#include "pdu.h"
/*
* Variable Binding class
*/
varBind::varBind(void)
{
newObject = 0;
newObjectValue = 0;
object = 0;
objectValue = 0;
}
varBind::varBind(asnObjectIdentifier *o, asnObject *a)
{
newObject = 0;
newObjectValue = 0;
object = o;
objectValue = a;
}
varBind::varBind(char *s, asnObject *a)
{
newObject = 0;
newObjectValue = 0;
setObject(s);
objectValue = a;
}
varBind::~varBind()
{
if (newObject)
delete object;
if (newObjectValue)
delete objectValue;
}
void
varBind::setObject(char *s)
{
if (newObject)
delete object;
object = new asnObjectIdentifier(s);
newObject = 1;
}
void
varBind::setObject(asnObjectIdentifier *o, int delLater)
{
if (newObject)
delete object;
object = o;
newObject = delLater;
}
void
varBind::setObjectValue(asnObject *a, int delLater)
{
if (newObjectValue)
delete objectValue;
objectValue = a;
newObjectValue = delLater;
}
int
varBind::encode(void)
{
// Shortcut the common case of a two byte sequence (tag and length)
const unsigned int offset = 2;
const unsigned int buflen = 8;
char buf[buflen];
if (object == 0)
return 0;
// Encode into buffer leaving room for initial sequence
char *a = asn + offset;
unsigned int alen = asnLength - offset;
int length = object->encode(a, alen);
if (length == 0)
return 0;
int totalLength = length;
// If objectValue is 0, send a null
if (objectValue == 0) {
objectValue = new asnNull;
newObjectValue = 1;
}
length = objectValue->encode(a + totalLength, alen - totalLength);
if (length == 0)
return 0;
totalLength += length;
if (totalLength >= alen)
return 0;
// Encode sequence into a temporary buffer
asnSequence s(totalLength);
length = s.encode(buf, buflen);
if (length == 0 || totalLength + length > asnLength)
return 0;
// Correct if shortcut failed
if (length != offset)
bcopy(asn + offset, asn + length, totalLength);
// Copy in sequence
bcopy(buf, asn, length);
return totalLength + length;
}
int
varBind::encode(char *a, unsigned int len)
{
setAsn(a, len);
return encode();
}
int
varBind::decode(void)
{
asnSequence s;
int length = s.decode(asn, asnLength);
if (length == 0 || asnLength - length < s.getValue())
return 0;
int totalLength = length;
// If object is 0, allocate one
if (object == 0) {
object = new asnObjectIdentifier;
newObject = 1;
}
length = object->decode(asn + totalLength, asnLength - totalLength);
if (length == 0)
return 0;
totalLength += length;
if (newObjectValue) {
delete objectValue;
objectValue = 0;
}
if (objectValue == 0) {
asnObject a;
a.setAsn(asn + totalLength, asnLength - totalLength);
switch (a.getTag()) {
case TAG_INTEGER:
objectValue = new asnInteger;
break;
case TAG_OCTET_STRING:
objectValue = new asnOctetString;
break;
case TAG_NULL:
objectValue = new asnNull;
break;
case TAG_OBJECT_IDENTIFIER:
objectValue = new asnObjectIdentifier;
break;
case TAG_NETADDR_IP:
objectValue = new snmpNetworkAddress;
break;
case TAG_IPADDRESS:
objectValue = new snmpIPaddress;
break;
case TAG_COUNTER:
objectValue = new snmpCounter;
break;
case TAG_GAUGE:
objectValue = new snmpGauge;
break;
case TAG_TIMETICKS:
objectValue = new snmpTimeticks;
break;
default:
return 0;
}
newObjectValue = 1;
}
length = objectValue->decode(asn + totalLength, asnLength - totalLength);
if (length == 0)
return 0;
totalLength += length;
return totalLength;
}
int
varBind::decode(char *a, unsigned int len)
{
setAsn(a, len);
return decode();
}
char *
varBind::getString(void)
{
if (object == 0)
return asnObject::getString();
char *os = object->getString();
char *vs;
if (objectValue == 0) {
asnNull n;
vs = n.getString();
} else
vs = objectValue->getString();
unsigned int l = strlen(os);
char *s = new char[l + strlen(vs) + 4];
bcopy(os, s, l);
strcpy(s + l, " = ");
strcpy(s + l + 3, vs);
delete os;
delete vs;
return s;
}
/*
* Variable Binding List
*/
varBindList::varBindList(void)
{
var = 0;
next = 0;
}
varBindList::~varBindList(void)
{
}
void
varBindList::appendVar(varBind *v)
{
for (varBindList **vbl = &next; *vbl != 0; vbl = &((*vbl)->next) )
;
*vbl = new varBindList;
(*vbl)->var = v;
}
void
varBindList::removeVar(varBind *v, int destroy)
{
for (varBindList **vbl = &next;
*vbl != 0 && (*vbl)->var != v; vbl = &((*vbl)->next) )
;
if (*vbl != 0) {
varBindList *vl = *vbl;
*vbl = vl->next;
delete vl;
}
if (destroy != 0)
delete v;
}
void
varBindList::clear(int destroy)
{
while (next != 0) {
varBindList *vl = next;
next = vl->next;
if (destroy != 0)
delete vl->var;
delete vl;
}
}
int
varBindList::encode(void)
{
// Shortcut the common case of a two byte sequence (tag and length)
const unsigned int offset = 2;
const unsigned int buflen = 8;
char buf[buflen];
// Encode into buffer leaving room for initial sequence
char *a = asn + offset;
unsigned int alen = asnLength - offset;
int length, totalLength = 0;
// Encode the list
for (varBindList *v = next; v != 0; v = v->next) {
length = v->var->encode(a + totalLength, alen - totalLength);
if (length == 0)
return 0;
totalLength += length;
}
// Encode sequence into a temporary buffer
asnSequence s(totalLength);
length = s.encode(buf, buflen);
if (length == 0 || totalLength + length > asnLength)
return 0;
// Correct if shortcut failed
if (length != offset)
bcopy(asn + offset, asn + length, totalLength);
// Copy in sequence
bcopy(buf, asn, length);
return totalLength + length;
}
int
varBindList::encode(char* a, unsigned int len)
{
setAsn(a, len);
return encode();
}
int
varBindList::decode(void)
{
// Decode the sequence
asnSequence s;
int length = s.decode(asn, asnLength);
if (length == 0 || asnLength - length < s.getValue())
return 0;
int totalLength = length;
// Decode the list
varBindList **vbl = &next;
for (length = 0; totalLength < asnLength; totalLength += length) {
varBind *vb = new varBind;
length = vb->decode(asn + totalLength, asnLength - totalLength);
if (length == 0) {
delete vb;
return totalLength;
}
if (*vbl == 0)
*vbl = new varBindList;
else
(*vbl)->next = 0;
(*vbl)->var = vb;
vbl = &((*vbl)->next);
}
return totalLength;
}
int
varBindList::decode(char *a, unsigned int len)
{
setAsn(a, len);
return decode();
}
char *
varBindList::getString(void)
{
const int stringlen = 4096;
char *s = new char[stringlen];
char *sp = s;
strcpy(sp, "{\n");
sp += strlen(sp);
for (varBindList **vbl = &next;
*vbl != 0 && (*vbl)->var != 0; vbl = &((*vbl)->next) ) {
*sp++ = '\t';
char *vs = (*vbl)->var->getString();
strcpy(sp, vs);
delete vs;
sp += strlen(sp);
*sp++ = ';';
*sp++ = '\n';
}
*sp++ = '}';
*sp++ = ';';
*sp = '\0';
return s;
}
/*
* An SNMP PDU.
*/
snmpPDU::snmpPDU(void)
{
}
snmpPDU::~snmpPDU(void)
{
varList.clear();
}
int
snmpPDU::encode(void)
{
const int buflen = 4096;
char buf[buflen];
int length = requestId.encode(buf, buflen);
if (length == 0)
return 0;
int totalLength = length;
length = errorStatus.encode(buf + totalLength, buflen - totalLength);
if (length == 0)
return 0;
totalLength += length;
length = errorIndex.encode(buf + totalLength, buflen - totalLength);
if (length == 0)
return 0;
totalLength += length;
length = varList.encode(buf + totalLength, buflen - totalLength);
if (length == 0)
return 0;
totalLength += length;
// Now encode choice and copy the buffer
asnChoice c(type, totalLength);
length = c.encode(asn, asnLength);
if (length == 0 || totalLength + length > asnLength)
return 0;
bcopy(buf, asn + length, totalLength);
return totalLength + length;
}
int
snmpPDU::encode(char *a, unsigned int len)
{
setAsn(a, len);
return encode();
}
int
snmpPDU::decode(void)
{
// Decode the choice
asnChoice c;
int length = c.decode(asn, asnLength);
if (length == 0 || asnLength - length < c.getValue())
return 0;
if (c.getTag() != type)
return 0;
int totalLength = length;
length = requestId.decode(asn + totalLength, asnLength - totalLength);
if (length == 0)
return 0;
totalLength += length;
length = errorStatus.decode(asn + totalLength, asnLength - totalLength);
if (length == 0)
return 0;
totalLength += length;
length = errorIndex.decode(asn + totalLength, asnLength - totalLength);
if (length == 0)
return 0;
totalLength += length;
length = varList.decode(asn + totalLength, asnLength - totalLength);
if (length == 0)
return 0;
return totalLength + length;
}
int
snmpPDU::decode(char *a, unsigned int len)
{
setAsn(a, len);
return decode();
}
char *
snmpPDU::getString(void)
{
const int stringlen = 4096;
char *s = new char[stringlen];
char *sp = s;
sprintf(sp, "Request Id = %u;\n", requestId.getValue());
sp += strlen(sp);
sprintf(sp, "Error Status = %u;\n", errorStatus.getValue());
sp += strlen(sp);
sprintf(sp, "Error Index = %u;\n", errorIndex.getValue());
sp += strlen(sp);
sprintf(sp, "Variable List = ");
sp += strlen(sp);
char *vs = varList.getString();
strcpy(sp, vs);
delete vs;
return s;
}
/*
* GetRequest PDU
*/
getRequestPDU::getRequestPDU(void)
{
setType(SNMP_GetRequest);
}
getRequestPDU::~getRequestPDU(void)
{
}
/*
* GetNextRequest PDU
*/
getNextRequestPDU::getNextRequestPDU(void)
{
setType(SNMP_GetNextRequest);
}
getNextRequestPDU::~getNextRequestPDU(void)
{
}
/*
* GetResponse PDU
*/
getResponsePDU::getResponsePDU(void)
{
setType(SNMP_GetResponse);
}
getResponsePDU::~getResponsePDU(void)
{
}
/*
* SetRequest PDU
*/
setRequestPDU::setRequestPDU(void)
{
setType(SNMP_SetRequest);
}
setRequestPDU::~setRequestPDU(void)
{
}
/*
* Trap PDU
*/
trapPDU::trapPDU(void)
{
}
trapPDU::~trapPDU()
{
varList.clear();
}
int
trapPDU::encode(void)
{
const int buflen = 4096;
char buf[buflen];
int length = enterprise.encode(buf, buflen);
if (length == 0)
return 0;
int totalLength = length;
length = agentAddress.encode(buf + totalLength, buflen - totalLength);
if (length == 0)
return 0;
totalLength += length;
length = trapType.encode(buf + totalLength, buflen - totalLength);
if (length == 0)
return 0;
totalLength += length;
length = specificTrap.encode(buf + totalLength, buflen - totalLength);
if (length == 0)
return 0;
totalLength += length;
length = timeStamp.encode(buf + totalLength, buflen - totalLength);
if (length == 0)
return 0;
totalLength += length;
length = varList.encode(buf + totalLength, buflen - totalLength);
if (length == 0)
return 0;
totalLength += length;
// Now encode choice and copy the buffer
asnChoice c(SNMP_Trap, totalLength);
length = c.encode(asn, asnLength);
if (length == 0 || totalLength + length > asnLength)
return 0;
bcopy(buf, asn + length, totalLength);
return totalLength + length;
}
int
trapPDU::encode(char *a, unsigned int len)
{
setAsn(a, len);
return encode();
}
int
trapPDU::decode(void)
{
// Decode the choice
asnChoice c;
int length = c.decode(asn, asnLength);
if (length == 0 || asnLength - length < c.getValue())
return 0;
if (c.getTag() != SNMP_Trap)
return 0;
int totalLength = length;
length = enterprise.decode(asn + totalLength, asnLength - totalLength);
if (length == 0)
return 0;
totalLength += length;
length = agentAddress.decode(asn + totalLength, asnLength - totalLength);
if (length == 0)
return 0;
totalLength += length;
length = trapType.decode(asn + totalLength, asnLength - totalLength);
if (length == 0)
return 0;
totalLength += length;
length = specificTrap.decode(asn + totalLength, asnLength - totalLength);
if (length == 0)
return 0;
totalLength += length;
length = timeStamp.decode(asn + totalLength, asnLength - totalLength);
if (length == 0)
return 0;
totalLength += length;
length = varList.decode(asn + totalLength, asnLength - totalLength);
if (length == 0)
return 0;
return totalLength + length;
}
int
trapPDU::decode(char *a, unsigned int len)
{
setAsn(a, len);
return decode();
}
char *
trapPDU::getString(void)
{
const int stringlen = 4096;
char *s = new char[stringlen];
char *sp = s;
char *gs = enterprise.getString();
sprintf(sp, "Enterprise = %s;\n", gs);
sp += strlen(sp);
delete gs;
gs = agentAddress.getString();
sprintf(sp, "Agent Address = %s;\n", gs);
sp += strlen(sp);
delete gs;
sprintf(sp, "Trap Type = %u;\n", trapType.getValue());
sp += strlen(sp);
sprintf(sp, "Specific Trap = %u;\n", specificTrap.getValue());
sp += strlen(sp);
sprintf(sp, "Time Stamp = %u;\n", timeStamp.getValue());
sp += strlen(sp);
sprintf(sp, "Variable List = ");
sp += strlen(sp);
char *vs = varList.getString();
for (char *p = vs; *p != 0; *sp++ = *p++) {
if (*p == '\n') {
*sp++ = '\n';
*p = '\t';
}
}
delete vs;
return s;
}