asn1.cpp
来自「HP公司的SNMP++的Win32版本源码」· C++ 代码 · 共 1,758 行 · 第 1/4 页
CPP
1,758 行
if ((int)(asn_length + (bufp - data)) > *datalength){
ASNERROR("overflow of message");
return NULL;
}
if (((int)asn_length > (intsize * 2 + 1)) ||
(((int)asn_length == (intsize * 2) + 1) && *bufp != 0x00)){
ASNERROR("I don't support such large integers");
return NULL;
}
*datalength -= (int)asn_length + (bufp - data);
if (*bufp & 0x80){
low = (unsigned long) -1; // integer is negative
high = (unsigned long) -1;
}
while(asn_length--){
high = (high << 8) | ((low & 0xFF000000) >> 24);
low = (low << 8) | *bufp++;
}
cp->low = low;
cp->high = high;
return bufp;
};
/*
* asn_build_unsigned_int64 - builds an ASN object containing a 64 bit integer.
* On entry, datalength is input as the number of valid bytes following
* "data". On exit, it is returned as the number of valid bytes
* following the end of this object.
*
* Returns a pointer to the first byte past the end
* of this object (i.e. the start of the next object).
* Returns NULL on any error.
*/
unsigned char * asn_build_unsigned_int64( unsigned char *data,
int *datalength,
unsigned char type,
struct counter64 *cp,
int countersize)
{
/*
* ASN.1 integer ::= 0x02 asnlength byte {byte}*
*/
unsigned long low, high;
unsigned long mask, mask2;
int add_null_byte = 0;
int intsize;
if (countersize != sizeof (struct counter64))
return NULL;
intsize = 8;
low = cp->low;
high = cp->high;
mask = 0xFF << (8 * (sizeof(long) - 1));
/* mask is 0xFF000000 on a big-endian machine */
if ((unsigned char)((high & mask) >> (8 * (sizeof(long) - 1))) & 0x80){
/* if MSB is set */
add_null_byte = 1;
intsize++;
}
/*
* Truncate "unnecessary" bytes off of the most significant end of this 2's
* complement integer.
* There should be no sequence of 9 consecutive 1's or 0's at the most
* significant end of the integer.
*/
mask2 = 0x1FF << ((8 * (sizeof(long) - 1)) - 1);
/* mask2 is 0xFF800000 on a big-endian machine */
while((((high & mask2) == 0) || ((high & mask2) == mask2))
&& intsize > 1){
intsize--;
high = (high << 8)
| ((low & mask) >> (8 * (sizeof(long) - 1)));
low <<= 8;
}
data = asn_build_header(data, datalength, type, intsize);
if (data == NULL)
return NULL;
if (*datalength < intsize)
return NULL;
*datalength -= intsize;
if (add_null_byte == 1){
*data++ = '\0';
intsize--;
}
while(intsize--){
*data++ = (unsigned char)((high & mask) >> (8 * (sizeof(long) - 1)));
high = (high << 8)
| ((low & mask) >> (8 * (sizeof(long) - 1)));
low <<= 8;
}
return data;
};
// create a pdu
struct snmp_pdu * snmp_pdu_create( int command)
{
struct snmp_pdu *pdu;
pdu = (struct snmp_pdu *)malloc(sizeof(struct snmp_pdu));
memset((char *)pdu, 0,sizeof(struct snmp_pdu));
pdu->command = command;
pdu->errstat = 0;
pdu->errindex = 0;
pdu->enterprise = NULL;
pdu->enterprise_length = 0;
pdu->variables = NULL;
return pdu;
};
// free a pdu
void snmp_free_pdu( struct snmp_pdu *pdu)
{
struct variable_list *vp, *ovp;
vp = pdu->variables;
while(vp){
// free the oid part
if (vp->name)
free((char *)vp->name);
// if deep data, then free as well
if (vp->val.string)
free((char *)vp->val.string);
ovp = vp;
// go to the next one
vp = vp->next_variable;
// free up vb itself
free((char *)ovp);
}
// if enterprise free it up
if (pdu->enterprise)
free((char *)pdu->enterprise);
// free up pdu itself
free((char *)pdu);
};
// add a null var to a pdu
void snmp_add_var(struct snmp_pdu *pdu,
oid *name,
int name_length,
SmiVALUE *smival)
{
struct variable_list *vars;
// if we don't have a vb list ,create one
if (pdu->variables == NULL)
pdu->variables = vars = (struct variable_list *)malloc(sizeof(struct variable_list));
else
{ // we have one, find the end
for(vars = pdu->variables; vars->next_variable; vars = vars->next_variable);
// create a new one
vars->next_variable = (struct variable_list *)malloc(sizeof(struct variable_list));
// bump ptr
vars = vars->next_variable;
}
// add the oid with no data
vars->next_variable = NULL;
// hook in the Oid portion
vars->name = (oid *)malloc(name_length * sizeof(oid));
// fixed
memcpy((char *)vars->name,(char *)name, name_length * sizeof(oid));
vars->name_length = name_length;
// hook in the SMI value
switch( smival->syntax)
{
// null , do nothing
case sNMP_SYNTAX_NULL:
case sNMP_SYNTAX_NOSUCHOBJECT:
case sNMP_SYNTAX_NOSUCHINSTANCE:
case sNMP_SYNTAX_ENDOFMIBVIEW:
{
vars->type = (unsigned char) smival->syntax;
vars->val.string = NULL;
vars->val_len = 0;
}
break;
// octects
case sNMP_SYNTAX_OCTETS:
case sNMP_SYNTAX_OPAQUE:
case sNMP_SYNTAX_IPADDR:
{
vars->type = (unsigned char) smival->syntax;
vars->val.string = (unsigned char *)malloc((unsigned)smival->value.string.len);
vars->val_len = (int) smival->value.string.len;
memcpy( (unsigned char *) vars->val.string,
(unsigned char *) smival->value.string.ptr,
(unsigned) smival->value.string.len);
}
break;
// oid
case sNMP_SYNTAX_OID:
{
vars->type = (unsigned char) smival->syntax;
vars->val_len = (int) smival->value.oid.len * sizeof(oid);
vars->val.objid = (oid *)malloc((unsigned)vars->val_len);
memcpy((unsigned long *)vars->val.objid,
(unsigned long *)smival->value.oid.ptr,
(unsigned) vars->val_len);
}
break;
case sNMP_SYNTAX_TIMETICKS:
case sNMP_SYNTAX_CNTR32:
case sNMP_SYNTAX_GAUGE32:
case sNMP_SYNTAX_UINT32:
{
long templong;
vars->type = (unsigned char) smival->syntax;
vars->val.integer = (long *)malloc(sizeof(long));
vars->val_len = sizeof(long);
templong = (long) smival->value.uNumber;
memcpy( (long*) vars->val.integer,
(long*) &templong,
sizeof(long));
}
break;
case sNMP_SYNTAX_INT32:
{
long templong;
vars->type = (unsigned char) smival->syntax;
vars->val.integer = (long *)malloc(sizeof(long));
vars->val_len = sizeof(long);
templong = (long) smival->value.sNumber;
memcpy( (long*) vars->val.integer,
(long*) &templong,
sizeof(long));
}
break;
// 64 bit counter
case sNMP_SYNTAX_CNTR64:
{
vars->type = ( unsigned char) smival->syntax;
vars->val.counter64 = (struct counter64 *)malloc( sizeof(struct counter64) );
vars->val_len = sizeof(struct counter64);
memcpy( (struct counter64*) vars->val.counter64,
(SmiLPCNTR64) &(smival->value.hNumber),
sizeof( SmiCNTR64));
}
break;
} // end switch
};
// build the authentication
// works for v1 or v2c
unsigned char *snmp_auth_build( unsigned char *data,
int *length,
long int version,
unsigned char *community,
int community_len,
int messagelen)
{
unsigned char *params;
int plen;
params = community;
plen = community_len;
data = asn_build_sequence(data,
length,
(unsigned char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
messagelen + plen + 5);
if (data == NULL){
ASNERROR("buildheader");
return NULL;
}
data = asn_build_int(data,
length,
(unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
(long *)&version,
sizeof(version));
if (data == NULL){
ASNERROR("buildint");
return NULL;
}
data = asn_build_string(data,
length,
(unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
params,
plen );
if (data == NULL){
ASNERROR("buildstring");
return NULL;
}
return (unsigned char *)data;
};
// build a variable binding
unsigned char * snmp_build_var_op(unsigned char *data,
oid * var_name,
int *var_name_len,
unsigned char var_val_type,
int var_val_len,
unsigned char *var_val,
int *listlength)
{
int dummyLen, headerLen;
unsigned char *dataPtr;
dummyLen = *listlength;
dataPtr = data;
data += 4;
dummyLen -=4;
if (dummyLen < 0)
return NULL;
headerLen = data - dataPtr;
*listlength -= headerLen;
data = asn_build_objid( data,
listlength,
(unsigned char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID),
var_name,
*var_name_len);
if (data == NULL){
ASNERROR("");
return NULL;
}
// based on the type...
switch(var_val_type){
case ASN_INTEGER:
data = asn_build_int( data,
listlength,
var_val_type,
(long *)var_val,
var_val_len);
break;
case SMI_GAUGE:
case SMI_COUNTER:
case SMI_TIMETICKS:
case SMI_UINTEGER:
data = asn_build_unsigned_int( data,
listlength,
var_val_type,
(unsigned long *)var_val,
var_val_len);
break;
case SMI_COUNTER64:
data = asn_build_unsigned_int64(data,
listlength,
var_val_type,
(struct counter64 *)var_val,
var_val_len);
break;
case ASN_OCTET_STR:
case SMI_IPADDRESS:
case SMI_OPAQUE:
case SMI_NSAP:
data = asn_build_string(data, listlength, var_val_type,
var_val, var_val_len);
break;
case ASN_OBJECT_ID:
data = asn_build_objid(data, listlength, var_val_type,
(oid *)var_val, var_val_len / sizeof(oid));
break;
case ASN_NULL:
data = asn_build_null(data, listlength, var_val_type);
break;
case ASN_BIT_STR:
data = asn_build_bitstring(data, listlength, var_val_type,
var_val, var_val_len);
break;
case SNMP_NOSUCHOBJECT:
case SNMP_NOSUCHINSTANCE:
case SNMP_ENDOFMIBVIEW:
data = asn_build_null(data, listlength, var_val_type);
break;
default:
ASNERROR("wrong type");
return NULL;
}
if (data == NULL){
ASNERROR("");
return NULL;
}
dummyLen = (data - dataPtr) - headerLen;
asn_build_sequence(dataPtr,
&dummyLen,
(unsigned char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),
dummyLen);
return data;
};
// serialize the pdu
int snmp_build( struct snmp_pdu *pdu,
unsigned char *packet,
int *out_length,
long version,
unsigned char* community,
int community_len)
{
unsigned char buf[SNMP_MSG_LENGTH];
unsigned char *cp;
struct variable_list *vp;
int length;
long int zero = 0;
int totallength;
length = *out_length;
cp = packet;
for(vp = pdu->variables; vp; vp = vp->next_variable){
cp = snmp_build_var_op( cp,
vp->name,
&vp->name_length,
vp->type,
vp->val_len,
(unsigned char *)vp->val.string,
&length);
if (cp == NULL)
return -1;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?