diff options
Diffstat (limited to 'src/RELATIVE-OID.c')
-rw-r--r-- | src/RELATIVE-OID.c | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/src/RELATIVE-OID.c b/src/RELATIVE-OID.c new file mode 100644 index 0000000..0181434 --- /dev/null +++ b/src/RELATIVE-OID.c @@ -0,0 +1,240 @@ +/*- + * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>. + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include <asn_internal.h> +#include <RELATIVE-OID.h> +#include <asn_codecs_prim.h> /* Encoder and decoder of a primitive type */ +#include <limits.h> /* for CHAR_BIT */ +#include <errno.h> + +/* + * RELATIVE-OID basic type description. + */ +static ber_tlv_tag_t asn_DEF_RELATIVE_OID_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (13 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_RELATIVE_OID = { + "RELATIVE-OID", + "RELATIVE_OID", + ASN__PRIMITIVE_TYPE_free, + RELATIVE_OID_print, + asn_generic_no_constraint, + ber_decode_primitive, + der_encode_primitive, + RELATIVE_OID_decode_xer, + RELATIVE_OID_encode_xer, + 0, 0, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_RELATIVE_OID_tags, + sizeof(asn_DEF_RELATIVE_OID_tags) + / sizeof(asn_DEF_RELATIVE_OID_tags[0]), + asn_DEF_RELATIVE_OID_tags, /* Same as above */ + sizeof(asn_DEF_RELATIVE_OID_tags) + / sizeof(asn_DEF_RELATIVE_OID_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + +static ssize_t +RELATIVE_OID__dump_body(const RELATIVE_OID_t *st, asn_app_consume_bytes_f *cb, void *app_key) { + ssize_t wrote = 0; + ssize_t ret; + int startn; + int i; + + for(i = 0, startn = 0; i < st->size; i++) { + uint8_t b = st->buf[i]; + if((b & 0x80)) /* Continuation expected */ + continue; + if(startn) { + /* Separate arcs */ + if(cb(".", 1, app_key) < 0) + return -1; + wrote++; + } + + ret = OBJECT_IDENTIFIER__dump_arc(&st->buf[startn], + i - startn + 1, 0, cb, app_key); + if(ret < 0) return -1; + wrote += ret; + + startn = i + 1; + } + + return wrote; +} + +int +RELATIVE_OID_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + const RELATIVE_OID_t *st = (const RELATIVE_OID_t *)sptr; + + (void)td; /* Unused argument */ + (void)ilevel; /* Unused argument */ + + if(!st || !st->buf) + return (cb("<absent>", 8, app_key) < 0) ? -1 : 0; + + /* Dump preamble */ + if(cb("{ ", 2, app_key) < 0) + return -1; + + if(RELATIVE_OID__dump_body(st, cb, app_key) < 0) + return -1; + + return (cb(" }", 2, app_key) < 0) ? -1 : 0; +} + +static enum xer_pbd_rval +RELATIVE_OID__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) { + RELATIVE_OID_t *st = (RELATIVE_OID_t *)sptr; + const char *chunk_end = (const char *)chunk_buf + chunk_size; + const char *endptr; + long s_arcs[6]; + long *arcs = s_arcs; + int arcs_count; + int ret; + + (void)td; + + arcs_count = OBJECT_IDENTIFIER_parse_arcs( + (const char *)chunk_buf, chunk_size, + arcs, sizeof(s_arcs)/sizeof(s_arcs[0]), &endptr); + if(arcs_count < 0) { + /* Expecting at least zero arcs */ + return XPBD_BROKEN_ENCODING; + } + if(endptr < chunk_end) { + /* We have a tail of unrecognized data. Check its safety. */ + if(!xer_is_whitespace(endptr, chunk_end - endptr)) + return XPBD_BROKEN_ENCODING; + } + + if((size_t)arcs_count > sizeof(s_arcs)/sizeof(s_arcs[0])) { + arcs = (long *)MALLOC(arcs_count * sizeof(long)); + if(!arcs) return XPBD_SYSTEM_FAILURE; + ret = OBJECT_IDENTIFIER_parse_arcs( + (const char *)chunk_buf, chunk_size, + arcs, arcs_count, &endptr); + if(ret != arcs_count) + return XPBD_SYSTEM_FAILURE; /* assert?.. */ + } + + /* + * Convert arcs into BER representation. + */ + ret = RELATIVE_OID_set_arcs(st, arcs, sizeof(*arcs), arcs_count); + if(arcs != s_arcs) FREEMEM(arcs); + + return ret ? XPBD_SYSTEM_FAILURE : XPBD_BODY_CONSUMED; +} + +asn_dec_rval_t +RELATIVE_OID_decode_xer(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + + return xer_decode_primitive(opt_codec_ctx, td, + sptr, sizeof(RELATIVE_OID_t), opt_mname, + buf_ptr, size, RELATIVE_OID__xer_body_decode); +} + +asn_enc_rval_t +RELATIVE_OID_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + RELATIVE_OID_t *st = (RELATIVE_OID_t *)sptr; + asn_enc_rval_t er; + + (void)ilevel; /* Unused argument */ + (void)flags; /* Unused argument */ + + if(!st || !st->buf) + _ASN_ENCODE_FAILED; + + er.encoded = RELATIVE_OID__dump_body(st, cb, app_key); + if(er.encoded < 0) _ASN_ENCODE_FAILED; + + _ASN_ENCODED_OK(er); +} + +int +RELATIVE_OID_get_arcs(RELATIVE_OID_t *roid, + void *arcs, unsigned int arc_type_size, unsigned int arc_slots) { + void *arcs_end = (char *)arcs + (arc_slots * arc_type_size); + int num_arcs = 0; + int startn = 0; + int i; + + if(!roid || !roid->buf) { + errno = EINVAL; + return -1; + } + + for(i = 0; i < roid->size; i++) { + uint8_t b = roid->buf[i]; + if((b & 0x80)) /* Continuation expected */ + continue; + + if(arcs < arcs_end) { + if(OBJECT_IDENTIFIER_get_single_arc( + &roid->buf[startn], + i - startn + 1, 0, + arcs, arc_type_size)) + return -1; + arcs = ((char *)arcs) + arc_type_size; + num_arcs++; + } + + startn = i + 1; + } + + return num_arcs; +} + +int +RELATIVE_OID_set_arcs(RELATIVE_OID_t *roid, void *arcs, unsigned int arc_type_size, unsigned int arcs_slots) { + uint8_t *buf; + uint8_t *bp; + unsigned int size; + unsigned int i; + + if(roid == NULL || arcs == NULL || arc_type_size < 1) { + errno = EINVAL; + return -1; + } + + /* + * Roughly estimate the maximum size necessary to encode these arcs. + */ + size = ((arc_type_size * CHAR_BIT + 6) / 7) * arcs_slots; + bp = buf = (uint8_t *)MALLOC(size + 1); + if(!buf) { + /* ENOMEM */ + return -1; + } + + /* + * Encode the arcs. + */ + for(i = 0; i < arcs_slots; i++, arcs = ((char *)arcs) + arc_type_size) { + bp += OBJECT_IDENTIFIER_set_single_arc(bp, + arcs, arc_type_size, 0); + } + + assert((unsigned)(bp - buf) <= size); + + /* + * Replace buffer. + */ + roid->size = (int)(bp - buf); + bp = roid->buf; + roid->buf = buf; + if(bp) FREEMEM(bp); + + return 0; +} + |