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 + -
显示快捷键?