⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asn1.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 5 页
字号:

  DEBUGDUMPSETUP("dump_recv", data, bufp - data);
  if ((*type == ASN_OPAQUE) &&
      (asn_length <= ASN_OPAQUE_COUNTER64_MX_BER_LEN) &&
      (*bufp == ASN_OPAQUE_TAG1) &&
       (*(bufp+1) == ASN_OPAQUE_I64)) {
      DEBUGMSG(("dump_recv", "Opaque %.2x %.2x: ", *bufp, *(bufp+1)));
    /* change type to Int64 */
    *type = *(bufp+1);
    /* value is encoded as special format */
    bufp = asn_parse_length(bufp + 2, &asn_length);
    if (_asn_parse_length_check("parse opaque int64", bufp, data,
                  asn_length, *datalength))
        return NULL;
  }
  /* this should always have been true until snmp gets int64 PDU types */
  else {
    sprintf(ebuf, "%s: wrong type: %d, len %d, buf bytes (%02X,%02X)",
             errpre, *type, (int)asn_length, *bufp, *(bufp+1));
    ERROR_MSG(ebuf);
    return NULL;
  }
  if (((int)asn_length > int64sizelimit) ||
      (((int)asn_length == int64sizelimit) && *bufp != 0x00)){
    _asn_length_err(errpre, (size_t)asn_length, int64sizelimit);
    return NULL;
  }
  *datalength -= (int)asn_length + (bufp - data);
  if (*bufp & 0x80){
    low = ~low; /* integer is negative */
    high = ~high;
  }

  while(asn_length--){
    high = (high << 8) | ((low & 0xFF000000) >> 24);
    low = (low << 8) | *bufp++;
  }

  cp->low = low;
  cp->high = high;

  DEBUGIF("dump_recv") {
    char i64buf[I64CHARSZ+1];
    printI64(i64buf, cp);
  }

  return bufp;
}


/*

  u_char * asn_build_signed_int64(
      u_char     *data         IN - pointer to start of object
      int        *datalength   IN/OUT - number of valid bytes left in buffer
      u_char      type         IN - asn type of object
      struct counter64 *cp     IN - pointer to counter struct
      int         countersize  IN - size of input buffer
 */
u_char *
asn_build_signed_int64(u_char *data,
		       size_t *datalength,
		       u_char type,
		       struct counter64 *cp,
		       size_t countersize)
{
/*
 * ASN.1 integer ::= 0x02 asnlength byte {byte}*
 */

    struct counter64 c64;
    register u_int mask, mask2;
    u_long low, high;
    size_t intsize;

  if (countersize != sizeof(struct counter64)){
    _asn_size_err("build int64", countersize, sizeof(struct counter64));
    return NULL;
  }
    intsize = 8;
    memcpy(&c64, cp, sizeof(struct counter64));  /* we're may modify it */
    low = c64.low;
    high = c64.high;
    
    /*
     * 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.
     */
    mask = ((u_int) 0xFF) << (8 * (sizeof(u_int) - 1));
    mask2 = ((u_int) 0x1FF) << ((8 * (sizeof(u_int) - 1)) - 1);
    /* mask is 0xFF800000 on a big-endian machine */
    while((((high & mask2) == 0) || ((high & mask2) == mask2)) && intsize > 1){
      intsize--;
      high = (high << 8)
        | ((low & mask) >> (8 * (sizeof(u_int) - 1)));
      low <<= 8;
    }
    /* until a real int64 gets incorperated into SNMP, we are going to
       encode it as an opaque instead.  First, we build the opaque
       header and then the int64 tag type we use to mark it as an
       int64 in the opaque string. */
    data = asn_build_header(data, datalength, ASN_OPAQUE, intsize+3);
    if (_asn_build_header_check("build int64", data, *datalength, intsize+3))
	return NULL;

    *data++ = ASN_OPAQUE_TAG1;
    *data++ = ASN_OPAQUE_I64;
    *data++ = (u_char)intsize;
    *datalength -= (3 + intsize);
    
    while(intsize--){
	*data++ = (u_char)((high & mask) >> (8 * (sizeof(u_int) - 1)));
	high = (high << 8)
	    | ((low & mask) >> (8 * (sizeof(u_int) - 1)));
	low <<= 8;
    }
    return data;
}

/*
 * asn_parse_float - pulls a single precision floating-point out of an opaque type.
 *
 *  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.

  u_char * asn_parse_float(
      u_char     *data         IN - pointer to start of object
      int        *datalength   IN/OUT - number of valid bytes left in buffer
      u_char     *type         OUT - asn type of object
      float      *floatp       IN/OUT - pointer to float
      int         floatsize    IN - size of output buffer
 */
u_char *
asn_parse_float(u_char *data,
		size_t *datalength,
		u_char *type,
		float *floatp,
		size_t floatsize)
{
    register u_char *bufp = data;
    u_long	    asn_length;
    union {
        float  floatVal;
	long   longVal;
	u_char c[sizeof(float)];
    } fu;

    if (floatsize != sizeof(float)){
	_asn_size_err("parse float", floatsize, sizeof(float));
	return NULL;
    }
    *type = *bufp++;
    bufp = asn_parse_length(bufp, &asn_length);
    if (_asn_parse_length_check("parse float", bufp, data,
                  asn_length, *datalength))
        return NULL;

    DEBUGDUMPSETUP("dump_recv", data, bufp - data + asn_length);
/* the float is encoded as an opaque */
    if ((*type == ASN_OPAQUE) &&
            (asn_length == ASN_OPAQUE_FLOAT_BER_LEN) &&
	    (*bufp == ASN_OPAQUE_TAG1) &&
	    (*(bufp+1) == ASN_OPAQUE_FLOAT)) {
      DEBUGMSG(("dump_recv", "Opaque %.2x %.2x: ", *bufp, *(bufp+1)));

        /* value is encoded as special format */
	bufp = asn_parse_length(bufp + 2, &asn_length);
	if (_asn_parse_length_check("parse opaque float", bufp, data,
                  asn_length, *datalength))
        return NULL;

	/* change type to Float */
	*type = ASN_OPAQUE_FLOAT;
    }

    if (asn_length != sizeof(float)) {
	_asn_size_err("parse seq float", asn_length, sizeof(float));
	return NULL;
    }

    *datalength -= (int)asn_length + (bufp - data);
    memcpy(&fu.c[0], bufp, asn_length);

   /* correct for endian differences */
    fu.longVal = ntohl(fu.longVal);	

    *floatp =  fu.floatVal;

    DEBUGMSG(("dump_recv", "%f",*floatp));
    return bufp;
}

/*
 * asn_build_float - builds an ASN object containing a single precision floating-point
 *                    number in an Opaque value.
 *
 *  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.

  u_char * asn_build_float(
      u_char     *data         IN - pointer to start of object
      int        *datalength   IN/OUT - number of valid bytes left in buffer
      u_char      type         IN - asn type of object
      float      *floatp       IN - pointer to float
      int         floatsize    IN - size of input buffer
 */
u_char *
asn_build_float(u_char *data,
		size_t *datalength,
		u_char type,
		float *floatp,
		size_t floatsize)
{
    union {
        float  floatVal;
        int    intVal;
	u_char c[sizeof(float)];
    } fu;

    if (floatsize != sizeof (float)) {
	_asn_size_err("build float", floatsize, sizeof(float));
	return NULL;
    }
/* encode the float as an opaque */
    /* turn into Opaque holding special tagged value */

    /* put the tag and length for the Opaque wrapper */
    data = asn_build_header(data, datalength, ASN_OPAQUE, floatsize+3);
    if (_asn_build_header_check("build float", data, *datalength, (floatsize+3)))
	return NULL;

    /* put the special tag and length */
    *data++ = ASN_OPAQUE_TAG1;
    *data++ = ASN_OPAQUE_FLOAT;
    *data++ = (u_char)floatsize;
    *datalength = *datalength - 3;

    fu.floatVal = *floatp;
    /* correct for endian differences */
    fu.intVal = htonl(fu.intVal);	

    *datalength -= floatsize;
    memcpy(data, &fu.c[0], floatsize);

    data += floatsize;
    return data;
}

/*

  u_char * asn_parse_double(
      u_char     *data         IN - pointer to start of object
      int        *datalength   IN/OUT - number of valid bytes left in buffer
      u_char     *type         OUT - asn type of object
      double     *doublep      IN/OUT - pointer to double
      int         doublesize   IN - size of output buffer
 */
u_char *
asn_parse_double(u_char *data,
		 size_t *datalength,
		 u_char *type,
		 double *doublep,
		 size_t doublesize)
{
    register u_char *bufp = data;
    u_long	    asn_length;
    long            tmp;
    union {
        double doubleVal;
        int    intVal[2];
	u_char c[sizeof(double)];
    } fu;
  

    if (doublesize != sizeof(double)){
	_asn_size_err("parse double", doublesize, sizeof(double));
	return NULL;
    }
    *type = *bufp++;
    bufp = asn_parse_length(bufp, &asn_length);
    if (_asn_parse_length_check("parse double", bufp, data,
                  asn_length, *datalength))
        return NULL;

    DEBUGDUMPSETUP("dump_recv", data, bufp - data + asn_length);
/* the double is encoded as an opaque */
    if ((*type == ASN_OPAQUE) &&
            (asn_length == ASN_OPAQUE_DOUBLE_BER_LEN) &&
	    (*bufp == ASN_OPAQUE_TAG1) &&
	    (*(bufp+1) == ASN_OPAQUE_DOUBLE)) {
      DEBUGMSG(("dump_recv", "Opaque %.2x %.2x: ", *bufp, *(bufp+1)));

        /* value is encoded as special format */
	bufp = asn_parse_length(bufp + 2, &asn_length);
	if (_asn_parse_length_check("parse opaque double", bufp, data,
                  asn_length, *datalength))
        return NULL;

	/* change type to Double */
	*type = ASN_OPAQUE_DOUBLE;
    }

    if (asn_length != sizeof(double)) {
	_asn_size_err("parse seq double", asn_length, sizeof(double));
	return NULL;
    }
    *datalength -= (int)asn_length + (bufp - data);
    memcpy(&fu.c[0], bufp, asn_length);

   /* correct for endian differences */

    tmp = ntohl(fu.intVal[0]);
    fu.intVal[0] = ntohl(fu.intVal[1]);
    fu.intVal[1] = tmp;
    	
    *doublep =  fu.doubleVal;
    DEBUGMSG(("dump_recv", "%d",*doublep));

    return bufp;
}

/*

  u_char * asn_build_double(
      u_char     *data         IN - pointer to start of object
      int        *datalength   IN/OUT - number of valid bytes left in buffer
      u_char      type         IN - asn type of object
      double     *doublep      IN - pointer to double
      int         doublesize   IN - size of input buffer
 */
u_char *
asn_build_double(u_char *data,
		 size_t *datalength,
		 u_char type,
		 double* doublep,
		 size_t doublesize)
{
    long  tmp;
    union {
        double doubleVal;
	int    intVal[2];
	u_char c[sizeof(double)];
    } fu;

    if (doublesize != sizeof(double)){
	_asn_size_err("build double", doublesize, sizeof(double));
	return NULL;
    }

/* encode the double as an opaque */
    /* turn into Opaque holding special tagged value */

    /* put the tag and length for the Opaque wrapper */
    data = asn_build_header(data, datalength, ASN_OPAQUE, doublesize+3);
    if (_asn_build_header_check("build double", data, *datalength, doublesize+3))
	return NULL;

    /* put the special tag and length */
    *data++ = ASN_OPAQUE_TAG1;
    *data++ = ASN_OPAQUE_DOUBLE;
    *data++ = (u_char)doublesize;
    *datalength = *datalength - 3;

    fu.doubleVal = *doublep;
    /* correct for endian differences */
    tmp = htonl(fu.intVal[0]);
    fu.intVal[0] = htonl(fu.intVal[1]);	
    fu.intVal[1] = tmp;
    *datalength -= doublesize;
    memcpy(data, &fu.c[0], doublesize);

    data += doublesize;
    return data;
}

#endif /* OPAQUE_SPECIAL_TYPES */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -