📄 object_identifier.c
字号:
/*- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */#include <asn_internal.h>#include <OBJECT_IDENTIFIER.h>#include <limits.h> /* for CHAR_BIT */#include <assert.h>#include <errno.h>/* * OBJECT IDENTIFIER basic type description. */static ber_tlv_tag_t asn_DEF_OBJECT_IDENTIFIER_tags[] = { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2))};asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER = { "OBJECT IDENTIFIER", "OBJECT_IDENTIFIER", ASN__PRIMITIVE_TYPE_free, OBJECT_IDENTIFIER_print, OBJECT_IDENTIFIER_constraint, ber_decode_primitive, der_encode_primitive, OBJECT_IDENTIFIER_decode_xer, OBJECT_IDENTIFIER_encode_xer, 0, /* Use generic outmost tag fetcher */ asn_DEF_OBJECT_IDENTIFIER_tags, sizeof(asn_DEF_OBJECT_IDENTIFIER_tags) / sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]), asn_DEF_OBJECT_IDENTIFIER_tags, /* Same as above */ sizeof(asn_DEF_OBJECT_IDENTIFIER_tags) / sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]), 0, 0, /* No members */ 0 /* No specifics */};intOBJECT_IDENTIFIER_constraint(asn_TYPE_descriptor_t *td, const void *sptr, asn_app_consume_bytes_f *app_errlog, void *app_key) { const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_t *)sptr; if(st && st->buf) { if(st->size < 1) { _ASN_ERRLOG(app_errlog, app_key, "%s: at least one numerical value " "expected (%s:%d)", td->name, __FILE__, __LINE__); return -1; } } else { _ASN_ERRLOG(app_errlog, app_key, "%s: value not given (%s:%d)", td->name, __FILE__, __LINE__); return -1; } return 0;}intOBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen, signed int add, void *rvbufp, unsigned int rvsize) { unsigned LE __attribute__ ((unused)) = 1; /* Little endian (x86) */ uint8_t *arcend = arcbuf + arclen; /* End of arc */ unsigned int cache = 0; /* No more than 14 significant bits */ unsigned char *rvbuf = (unsigned char *)rvbufp; unsigned char *rvstart = rvbuf; /* Original start of the value buffer */ int inc; /* Return value growth direction */ rvsize *= CHAR_BIT; /* bytes to bits */ arclen *= 7; /* bytes to bits */ /* * The arc has the number of bits * cannot be represented using supplied return value type. */ if(arclen > rvsize) { if(arclen > (rvsize + CHAR_BIT)) { errno = ERANGE; /* Overflow */ return -1; } else { /* * Even if the number of bits in the arc representation * is higher than the width of supplied * return value * type, there is still possible to fit it when there * are few unused high bits in the arc value * representaion. * * Moreover, there is a possibility that the * number could actually fit the arc space, given * that add is negative, but we don't handle * such "temporary lack of precision" situation here. * May be considered as a bug. */ uint8_t mask = (0xff << (7-(arclen - rvsize))) & 0x7f; if((*arcbuf & mask)) { errno = ERANGE; /* Overflow */ return -1; } /* Fool the routine computing unused bits */ arclen -= 7; cache = *arcbuf & 0x7f; arcbuf++; } } /* Faster path for common size */ if(rvsize == (CHAR_BIT * sizeof(unsigned long))) { unsigned long accum; /* Gather all bits into the accumulator */ for(accum = cache; arcbuf < arcend; arcbuf++) accum = (accum << 7) | (*arcbuf & ~0x80); if(accum < (unsigned)-add) { errno = ERANGE; /* Overflow */ return -1; } *(unsigned long *)rvbuf = accum + add; /* alignment OK! */ return 0; }#ifndef WORDS_BIGENDIAN if(*(unsigned char *)&LE) { /* Little endian (x86) */ /* "Convert" to big endian */ rvbuf += rvsize / CHAR_BIT - 1; rvstart--; inc = -1; /* Descending */ } else#endif /* !WORDS_BIGENDIAN */ inc = +1; /* Big endian is known [at compile time] */ { int bits; /* typically no more than 3-4 bits */ /* Clear the high unused bits */ for(bits = rvsize - arclen; bits > CHAR_BIT; rvbuf += inc, bits -= CHAR_BIT) *rvbuf = 0; /* Fill the body of a value */ for(; arcbuf < arcend; arcbuf++) { cache = (cache << 7) | (*arcbuf & 0x7f); bits += 7; if(bits >= CHAR_BIT) { bits -= CHAR_BIT; *rvbuf = (cache >> bits); rvbuf += inc; } } if(bits) { *rvbuf = cache; rvbuf += inc; } } if(add) { for(rvbuf -= inc; rvbuf != rvstart; rvbuf -= inc) { int v = add + *rvbuf; if(v & (-1 << CHAR_BIT)) { *rvbuf = (unsigned char)(v + (1 << CHAR_BIT)); add = -1; } else { *rvbuf = v; break; } } if(rvbuf == rvstart) { /* No space to carry over */ errno = ERANGE; /* Overflow */ return -1; } } return 0;}ssize_tOBJECT_IDENTIFIER__dump_arc(uint8_t *arcbuf, int arclen, int add, asn_app_consume_bytes_f *cb, void *app_key) { char scratch[64]; /* Conservative estimate */ unsigned long accum; /* Bits accumulator */ char *p; /* Position in the scratch buffer */ if(OBJECT_IDENTIFIER_get_single_arc(arcbuf, arclen, add, &accum, sizeof(accum))) return -1; if(accum) { ssize_t len; /* Fill the scratch buffer in reverse. */ p = scratch + sizeof(scratch); for(; accum; accum /= 10) *(--p) = (char)(accum % 10) + 0x30; /* Put a digit */ len = sizeof(scratch) - (p - scratch); if(cb(p, len, app_key) < 0) return -1; return len; } else { *scratch = 0x30; if(cb(scratch, 1, app_key) < 0) return -1; return 1; }}intOBJECT_IDENTIFIER_print_arc(uint8_t *arcbuf, int arclen, int add, asn_app_consume_bytes_f *cb, void *app_key) { if(OBJECT_IDENTIFIER__dump_arc(arcbuf, arclen, add, cb, app_key) < 0) return -1; return 0;}static ssize_tOBJECT_IDENTIFIER__dump_body(const OBJECT_IDENTIFIER_t *st, asn_app_consume_bytes_f *cb, void *app_key) { ssize_t wrote_len = 0; int startn; int add = 0; 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 == 0) { /* * First two arcs are encoded through the backdoor. */ if(i) { add = -80; if(cb("2", 1, app_key) < 0) return -1; } else if(b <= 39) { add = 0; if(cb("0", 1, app_key) < 0) return -1; } else if(b < 79) { add = -40; if(cb("1", 1, app_key) < 0) return -1; } else { add = -80; if(cb("2", 1, app_key) < 0) return -1; } wrote_len += 1; } if(cb(".", 1, app_key) < 0) /* Separate arcs */ return -1; add = OBJECT_IDENTIFIER__dump_arc(&st->buf[startn], i - startn + 1, add, cb, app_key); if(add < 0) return -1; wrote_len += 1 + add; startn = i + 1; add = 0; } return wrote_len;}static enum xer_pbd_rvalOBJECT_IDENTIFIER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) { OBJECT_IDENTIFIER_t *st = (OBJECT_IDENTIFIER_t *)sptr; const char *chunk_end = (const char *)chunk_buf + chunk_size; const char *endptr; long s_arcs[10]; 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 more than 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 = OBJECT_IDENTIFIER_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_tOBJECT_IDENTIFIER_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname, void *buf_ptr, size_t size) { return xer_decode_primitive(opt_codec_ctx, td, sptr, sizeof(OBJECT_IDENTIFIER_t), opt_mname, buf_ptr, size, OBJECT_IDENTIFIER__xer_body_decode);}asn_enc_rval_tOBJECT_IDENTIFIER_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) { const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_t *)sptr; asn_enc_rval_t er; (void)ilevel; (void)flags; if(!st || !st->buf) _ASN_ENCODE_FAILED; er.encoded = OBJECT_IDENTIFIER__dump_body(st, cb, app_key); if(er.encoded < 0) _ASN_ENCODE_FAILED; return er;}intOBJECT_IDENTIFIER_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_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(OBJECT_IDENTIFIER__dump_body(st, cb, app_key) < 0) return -1; return (cb(" }", 2, app_key) < 0) ? -1 : 0;}intOBJECT_IDENTIFIER_get_arcs(OBJECT_IDENTIFIER_t *oid, void *arcs, unsigned int arc_type_size, unsigned int arc_slots) { void *arcs_end = (char *)arcs + (arc_type_size * arc_slots); int num_arcs = 0; int startn = 0; int add = 0; int i; if(!oid || !oid->buf || (arc_slots && arc_type_size <= 1)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -