📄 asn1.c
字号:
* 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 { snprintf(ebuf, sizeof(ebuf), "%s: wrong type: %d, len %d, buf bytes (%02X,%02X)", errpre, *type, (int) asn_length, *bufp, *(bufp + 1)); ebuf[ sizeof(ebuf)-1 ] = 0; 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("dumpv_recv") { char i64buf[I64CHARSZ + 1]; printI64(i64buf, cp); DEBUGMSG(("dumpv_recv", "Integer64: %s", i64buf)); } 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;#ifndef SNMP_NO_DEBUGGING u_char *initdatap = data;#endif 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; } DEBUGDUMPSETUP("send", initdatap, data - initdatap); DEBUGIF("dumpv_send") { char i64buf[I64CHARSZ + 1]; printU64(i64buf, cp); DEBUGMSG(("dumpv_send", i64buf)); } 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("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)) { /* * 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(("dumpv_recv", "Opaque float: %f\n", *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;#ifndef SNMP_NO_DEBUGGING u_char *initdatap = data;#endif 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); DEBUGDUMPSETUP("send", initdatap, data - initdatap); DEBUGMSG(("dumpv_send", "Opaque float: %f\n", *floatp)); 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("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)) { /* * 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(("dumpv_recv", " Opaque Double:\t%f\n", *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;#ifndef SNMP_NO_DEBUGGING u_char *initdatap = data;#endif 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; /* *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -