summaryrefslogtreecommitdiff
path: root/include/net-snmp/library/asn1.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/net-snmp/library/asn1.h')
-rw-r--r--include/net-snmp/library/asn1.h455
1 files changed, 455 insertions, 0 deletions
diff --git a/include/net-snmp/library/asn1.h b/include/net-snmp/library/asn1.h
new file mode 100644
index 0000000..52ecc3b
--- /dev/null
+++ b/include/net-snmp/library/asn1.h
@@ -0,0 +1,455 @@
+#ifndef ASN1_H
+#define ASN1_H
+
+#include <net-snmp/library/oid.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PARSE_PACKET 0
+#define DUMP_PACKET 1
+
+ /*
+ * Definitions for Abstract Syntax Notation One, ASN.1
+ * As defined in ISO/IS 8824 and ISO/IS 8825
+ *
+ *
+ */
+/***********************************************************
+ Copyright 1988, 1989 by Carnegie Mellon University
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of CMU not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+******************************************************************/
+
+
+#define MIN_OID_LEN 2
+#define MAX_OID_LEN 128 /* max subid's in an oid */
+#ifndef MAX_NAME_LEN /* conflicts with some libraries */
+#define MAX_NAME_LEN MAX_OID_LEN /* obsolete. use MAX_OID_LEN */
+#endif
+
+#define OID_LENGTH(x) (sizeof(x)/sizeof(oid))
+
+
+#define ASN_BOOLEAN ((u_char)0x01)
+#define ASN_INTEGER ((u_char)0x02)
+#define ASN_BIT_STR ((u_char)0x03)
+#define ASN_OCTET_STR ((u_char)0x04)
+#define ASN_NULL ((u_char)0x05)
+#define ASN_OBJECT_ID ((u_char)0x06)
+#define ASN_SEQUENCE ((u_char)0x10)
+#define ASN_SET ((u_char)0x11)
+
+#define ASN_UNIVERSAL ((u_char)0x00)
+#define ASN_APPLICATION ((u_char)0x40)
+#define ASN_CONTEXT ((u_char)0x80)
+#define ASN_PRIVATE ((u_char)0xC0)
+
+#define ASN_PRIMITIVE ((u_char)0x00)
+#define ASN_CONSTRUCTOR ((u_char)0x20)
+
+#define ASN_LONG_LEN (0x80)
+#define ASN_EXTENSION_ID (0x1F)
+#define ASN_BIT8 (0x80)
+
+#define IS_CONSTRUCTOR(byte) ((byte) & ASN_CONSTRUCTOR)
+#define IS_EXTENSION_ID(byte) (((byte) & ASN_EXTENSION_ID) == ASN_EXTENSION_ID)
+
+ struct counter64 {
+ u_long high;
+ u_long low;
+ };
+
+#ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
+ typedef struct counter64 integer64;
+ typedef struct counter64 unsigned64;
+
+ /*
+ * The BER inside an OPAQUE is an context specific with a value of 48 (0x30)
+ * plus the "normal" tag. For a Counter64, the tag is 0x46 (i.e., an
+ * applications specific tag with value 6). So the value for a 64 bit
+ * counter is 0x46 + 0x30, or 0x76 (118 base 10). However, values
+ * greater than 30 can not be encoded in one octet. So the first octet
+ * has the class, in this case context specific (ASN_CONTEXT), and
+ * the special value (i.e., 31) to indicate that the real value follows
+ * in one or more octets. The high order bit of each following octet
+ * indicates if the value is encoded in additional octets. A high order
+ * bit of zero, indicates the last. For this "hack", only one octet
+ * will be used for the value.
+ */
+
+ /*
+ * first octet of the tag
+ */
+#define ASN_OPAQUE_TAG1 (ASN_CONTEXT | ASN_EXTENSION_ID)
+ /*
+ * base value for the second octet of the tag - the
+ * second octet was the value for the tag
+ */
+#define ASN_OPAQUE_TAG2 ((u_char)0x30)
+
+#define ASN_OPAQUE_TAG2U ((u_char)0x2f) /* second octet of tag for union */
+
+ /*
+ * All the ASN.1 types for SNMP "should have been" defined in this file,
+ * but they were not. (They are defined in snmp_impl.h) Thus, the tag for
+ * Opaque and Counter64 is defined, again, here with a different names.
+ */
+#define ASN_APP_OPAQUE (ASN_APPLICATION | 4)
+#define ASN_APP_COUNTER64 (ASN_APPLICATION | 6)
+#define ASN_APP_FLOAT (ASN_APPLICATION | 8)
+#define ASN_APP_DOUBLE (ASN_APPLICATION | 9)
+#define ASN_APP_I64 (ASN_APPLICATION | 10)
+#define ASN_APP_U64 (ASN_APPLICATION | 11)
+#define ASN_APP_UNION (ASN_PRIVATE | 1) /* or ASN_PRIV_UNION ? */
+
+ /*
+ * value for Counter64
+ */
+#define ASN_OPAQUE_COUNTER64 (ASN_OPAQUE_TAG2 + ASN_APP_COUNTER64)
+ /*
+ * max size of BER encoding of Counter64
+ */
+#define ASN_OPAQUE_COUNTER64_MX_BER_LEN 12
+
+ /*
+ * value for Float
+ */
+#define ASN_OPAQUE_FLOAT (ASN_OPAQUE_TAG2 + ASN_APP_FLOAT)
+ /*
+ * size of BER encoding of Float
+ */
+#define ASN_OPAQUE_FLOAT_BER_LEN 7
+
+ /*
+ * value for Double
+ */
+#define ASN_OPAQUE_DOUBLE (ASN_OPAQUE_TAG2 + ASN_APP_DOUBLE)
+ /*
+ * size of BER encoding of Double
+ */
+#define ASN_OPAQUE_DOUBLE_BER_LEN 11
+
+ /*
+ * value for Integer64
+ */
+#define ASN_OPAQUE_I64 (ASN_OPAQUE_TAG2 + ASN_APP_I64)
+ /*
+ * max size of BER encoding of Integer64
+ */
+#define ASN_OPAQUE_I64_MX_BER_LEN 11
+
+ /*
+ * value for Unsigned64
+ */
+#define ASN_OPAQUE_U64 (ASN_OPAQUE_TAG2 + ASN_APP_U64)
+ /*
+ * max size of BER encoding of Unsigned64
+ */
+#define ASN_OPAQUE_U64_MX_BER_LEN 12
+
+#endif /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */
+
+
+#define ASN_PRIV_INCL_RANGE (ASN_PRIVATE | 2)
+#define ASN_PRIV_EXCL_RANGE (ASN_PRIVATE | 3)
+#define ASN_PRIV_DELEGATED (ASN_PRIVATE | 5)
+#define ASN_PRIV_IMPLIED_OCTET_STR (ASN_PRIVATE | ASN_OCTET_STR) /* 4 */
+#define ASN_PRIV_IMPLIED_OBJECT_ID (ASN_PRIVATE | ASN_OBJECT_ID) /* 6 */
+#define ASN_PRIV_RETRY (ASN_PRIVATE | 7) /* 199 */
+#define IS_DELEGATED(x) ((x) == ASN_PRIV_DELEGATED)
+
+
+ int asn_check_packet(u_char *, size_t);
+ NETSNMP_IMPORT
+ u_char *asn_parse_int(u_char *, size_t *, u_char *, long *,
+ size_t);
+ NETSNMP_IMPORT
+ u_char *asn_build_int(u_char *, size_t *, u_char, const long *,
+ size_t);
+ NETSNMP_IMPORT
+ u_char *asn_parse_unsigned_int(u_char *, size_t *, u_char *,
+ u_long *, size_t);
+ NETSNMP_IMPORT
+ u_char *asn_build_unsigned_int(u_char *, size_t *, u_char,
+ const u_long *, size_t);
+ NETSNMP_IMPORT
+ u_char *asn_parse_string(u_char *, size_t *, u_char *,
+ u_char *, size_t *);
+ NETSNMP_IMPORT
+ u_char *asn_build_string(u_char *, size_t *, u_char,
+ const u_char *, size_t);
+ NETSNMP_IMPORT
+ u_char *asn_parse_header(u_char *, size_t *, u_char *);
+ u_char *asn_parse_sequence(u_char *, size_t *, u_char *, u_char expected_type, /* must be this type */
+ const char *estr); /* error message prefix */
+ NETSNMP_IMPORT
+ u_char *asn_build_header(u_char *, size_t *, u_char, size_t);
+ NETSNMP_IMPORT
+ u_char *asn_build_sequence(u_char *, size_t *, u_char, size_t);
+ NETSNMP_IMPORT
+ u_char *asn_parse_length(u_char *, u_long *);
+ NETSNMP_IMPORT
+ u_char *asn_build_length(u_char *, size_t *, size_t);
+ NETSNMP_IMPORT
+ u_char *asn_parse_objid(u_char *, size_t *, u_char *, oid *,
+ size_t *);
+ NETSNMP_IMPORT
+ u_char *asn_build_objid(u_char *, size_t *, u_char, oid *,
+ size_t);
+ NETSNMP_IMPORT
+ u_char *asn_parse_null(u_char *, size_t *, u_char *);
+ NETSNMP_IMPORT
+ u_char *asn_build_null(u_char *, size_t *, u_char);
+ NETSNMP_IMPORT
+ u_char *asn_parse_bitstring(u_char *, size_t *, u_char *,
+ u_char *, size_t *);
+ NETSNMP_IMPORT
+ u_char *asn_build_bitstring(u_char *, size_t *, u_char,
+ const u_char *, size_t);
+ NETSNMP_IMPORT
+ u_char *asn_parse_unsigned_int64(u_char *, size_t *, u_char *,
+ struct counter64 *, size_t);
+ NETSNMP_IMPORT
+ u_char *asn_build_unsigned_int64(u_char *, size_t *, u_char,
+ const struct counter64 *, size_t);
+ u_char *asn_parse_signed_int64(u_char *, size_t *, u_char *,
+ struct counter64 *, size_t);
+ u_char *asn_build_signed_int64(u_char *, size_t *, u_char,
+ const struct counter64 *, size_t);
+ u_char *asn_build_float(u_char *, size_t *, u_char, const float *,
+ size_t);
+ u_char *asn_parse_float(u_char *, size_t *, u_char *, float *,
+ size_t);
+ u_char *asn_build_double(u_char *, size_t *, u_char, const double *,
+ size_t);
+ u_char *asn_parse_double(u_char *, size_t *, u_char *,
+ double *, size_t);
+
+#ifdef NETSNMP_USE_REVERSE_ASNENCODING
+
+ /*
+ * Re-allocator function for below.
+ */
+
+ int asn_realloc(u_char **, size_t *);
+
+ /*
+ * Re-allocating reverse ASN.1 encoder functions. Synopsis:
+ *
+ * u_char *buf = (u_char*)malloc(100);
+ * u_char type = (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER);
+ * size_t buf_len = 100, offset = 0;
+ * long data = 12345;
+ * int allow_realloc = 1;
+ *
+ * if (asn_realloc_rbuild_int(&buf, &buf_len, &offset, allow_realloc,
+ * type, &data, sizeof(long)) == 0) {
+ * error;
+ * }
+ *
+ * NOTE WELL: after calling one of these functions with allow_realloc
+ * non-zero, buf might have moved, buf_len might have grown and
+ * offset will have increased by the size of the encoded data.
+ * You should **NEVER** do something like this:
+ *
+ * u_char *buf = (u_char *)malloc(100), *ptr;
+ * u_char type = (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER);
+ * size_t buf_len = 100, offset = 0;
+ * long data1 = 1234, data2 = 5678;
+ * int rc = 0, allow_realloc = 1;
+ *
+ * rc = asn_realloc_rbuild_int(&buf, &buf_len, &offset, allow_realloc,
+ * type, &data1, sizeof(long));
+ * ptr = buf[buf_len - offset]; / * points at encoding of data1 * /
+ * if (rc == 0) {
+ * error;
+ * }
+ * rc = asn_realloc_rbuild_int(&buf, &buf_len, &offset, allow_realloc,
+ * type, &data2, sizeof(long));
+ * make use of ptr here;
+ *
+ *
+ * ptr is **INVALID** at this point. In general, you should store the
+ * offset value and compute pointers when you need them:
+ *
+ *
+ *
+ * u_char *buf = (u_char *)malloc(100), *ptr;
+ * u_char type = (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER);
+ * size_t buf_len = 100, offset = 0, ptr_offset;
+ * long data1 = 1234, data2 = 5678;
+ * int rc = 0, allow_realloc = 1;
+ *
+ * rc = asn_realloc_rbuild_int(&buf, &buf_len, &offset, allow_realloc,
+ * type, &data1, sizeof(long));
+ * ptr_offset = offset;
+ * if (rc == 0) {
+ * error;
+ * }
+ * rc = asn_realloc_rbuild_int(&buf, &buf_len, &offset, allow_realloc,
+ * type, &data2, sizeof(long));
+ * ptr = buf + buf_len - ptr_offset
+ * make use of ptr here;
+ *
+ *
+ *
+ * Here, you can see that ptr will be a valid pointer even if the block of
+ * memory has been moved, as it may well have been. Plenty of examples of
+ * usage all over asn1.c, snmp_api.c, snmpusm.c.
+ *
+ * The other thing you should **NEVER** do is to pass a pointer to a buffer
+ * on the stack as the first argument when allow_realloc is non-zero, unless
+ * you really know what you are doing and your machine/compiler allows you to
+ * free non-heap memory. There are rumours that such things exist, but many
+ * consider them no more than the wild tales of a fool.
+ *
+ * Of course, you can pass allow_realloc as zero, to indicate that you do not
+ * wish the packet buffer to be reallocated for some reason; perhaps because
+ * it is on the stack. This may be useful to emulate the functionality of
+ * the old API:
+ *
+ * u_char my_static_buffer[100], *cp = NULL;
+ * size_t my_static_buffer_len = 100;
+ * float my_pi = (float)22/(float)7;
+ *
+ * cp = asn_rbuild_float(my_static_buffer, &my_static_buffer_len,
+ * ASN_OPAQUE_FLOAT, &my_pi, sizeof(float));
+ * if (cp == NULL) {
+ * error;
+ * }
+ *
+ *
+ * IS EQUIVALENT TO:
+ *
+ *
+ * u_char my_static_buffer[100];
+ * size_t my_static_buffer_len = 100, my_offset = 0;
+ * float my_pi = (float)22/(float)7;
+ * int rc = 0;
+ *
+ * rc = asn_realloc_rbuild_float(&my_static_buffer, &my_static_buffer_len,
+ * &my_offset, 0,
+ * ASN_OPAQUE_FLOAT, &my_pi, sizeof(float));
+ * if (rc == 0) {
+ * error;
+ * }
+ *
+ *
+ */
+
+
+ int asn_realloc_rbuild_int(u_char ** pkt, size_t * pkt_len,
+ size_t * offset,
+ int allow_realloc, u_char type,
+ const long *data, size_t data_size);
+
+ int asn_realloc_rbuild_string(u_char ** pkt,
+ size_t * pkt_len,
+ size_t * offset,
+ int allow_realloc,
+ u_char type,
+ const u_char * data,
+ size_t data_size);
+
+ int asn_realloc_rbuild_unsigned_int(u_char ** pkt,
+ size_t * pkt_len,
+ size_t * offset,
+ int allow_realloc,
+ u_char type,
+ const u_long * data,
+ size_t data_size);
+
+ int asn_realloc_rbuild_header(u_char ** pkt,
+ size_t * pkt_len,
+ size_t * offset,
+ int allow_realloc,
+ u_char type,
+ size_t data_size);
+
+ int asn_realloc_rbuild_sequence(u_char ** pkt,
+ size_t * pkt_len,
+ size_t * offset,
+ int allow_realloc,
+ u_char type,
+ size_t data_size);
+
+ int asn_realloc_rbuild_length(u_char ** pkt,
+ size_t * pkt_len,
+ size_t * offset,
+ int allow_realloc,
+ size_t data_size);
+
+ int asn_realloc_rbuild_objid(u_char ** pkt,
+ size_t * pkt_len,
+ size_t * offset,
+ int allow_realloc,
+ u_char type, const oid *,
+ size_t);
+
+ int asn_realloc_rbuild_null(u_char ** pkt,
+ size_t * pkt_len,
+ size_t * offset,
+ int allow_realloc,
+ u_char type);
+
+ int asn_realloc_rbuild_bitstring(u_char ** pkt,
+ size_t * pkt_len,
+ size_t * offset,
+ int allow_realloc,
+ u_char type,
+ const u_char * data,
+ size_t data_size);
+
+ int asn_realloc_rbuild_unsigned_int64(u_char ** pkt,
+ size_t * pkt_len,
+ size_t * offset,
+ int allow_realloc,
+ u_char type,
+ struct counter64
+ const *data, size_t);
+
+ int asn_realloc_rbuild_signed_int64(u_char ** pkt,
+ size_t * pkt_len,
+ size_t * offset,
+ int allow_realloc,
+ u_char type,
+ const struct counter64 *data,
+ size_t);
+
+ int asn_realloc_rbuild_float(u_char ** pkt,
+ size_t * pkt_len,
+ size_t * offset,
+ int allow_realloc,
+ u_char type, const float *data,
+ size_t data_size);
+
+ int asn_realloc_rbuild_double(u_char ** pkt,
+ size_t * pkt_len,
+ size_t * offset,
+ int allow_realloc,
+ u_char type, const double *data,
+ size_t data_size);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* ASN1_H */