blob: 33bfd4a12b7c5480bec706806c7a97808523f93c [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001/*-
Lev Walkina5972be2017-09-29 23:15:58 -07002 * Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>.
Lev Walkin2c34aad2005-03-10 11:50:24 +00003 * All rights reserved.
Lev Walkinf15320b2004-06-03 03:38:44 +00004 * Redistribution and modifications are permitted subject to BSD license.
5 */
Lev Walkina9cc46e2004-09-22 16:06:28 +00006#include <asn_internal.h>
Lev Walkinf15320b2004-06-03 03:38:44 +00007#include <RELATIVE-OID.h>
Lev Walkin725883b2006-10-09 12:07:58 +00008#include <OCTET_STRING.h>
Lev Walkin3256d6f2004-10-21 11:22:12 +00009#include <asn_codecs_prim.h> /* Encoder and decoder of a primitive type */
Lev Walkin0787ff02004-06-17 23:43:39 +000010#include <limits.h> /* for CHAR_BIT */
Lev Walkinf15320b2004-06-03 03:38:44 +000011#include <errno.h>
12
13/*
14 * RELATIVE-OID basic type description.
15 */
Wim Lewis18c2ec92014-07-29 11:30:10 -070016static const ber_tlv_tag_t asn_DEF_RELATIVE_OID_tags[] = {
Lev Walkinf15320b2004-06-03 03:38:44 +000017 (ASN_TAG_CLASS_UNIVERSAL | (13 << 2))
18};
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +080019asn_TYPE_operation_t asn_OP_RELATIVE_OID = {
Lev Walkin8e8078a2004-09-26 13:10:40 +000020 ASN__PRIMITIVE_TYPE_free,
Lev Walkina9cc46e2004-09-22 16:06:28 +000021 RELATIVE_OID_print,
Lev Walkincd2f48e2017-08-10 02:14:59 -070022 OCTET_STRING_compare, /* Implemented in terms of opaque comparison */
Lev Walkin8e8078a2004-09-26 13:10:40 +000023 ber_decode_primitive,
24 der_encode_primitive,
Lev Walkin92302252004-10-23 10:16:51 +000025 RELATIVE_OID_decode_xer,
Lev Walkina9cc46e2004-09-22 16:06:28 +000026 RELATIVE_OID_encode_xer,
Lev Walkincc159472017-07-06 08:26:36 -070027#ifdef ASN_DISABLE_OER_SUPPORT
28 0,
29 0,
30#else
Lev Walkinb5b524b2017-10-13 03:14:03 -070031 RELATIVE_OID_decode_oer,
32 RELATIVE_OID_encode_oer,
Lev Walkincc159472017-07-06 08:26:36 -070033#endif /* ASN_DISABLE_OER_SUPPORT */
Lev Walkinb33425f2017-07-14 14:59:52 +040034#ifdef ASN_DISABLE_PER_SUPPORT
35 0,
36 0,
37#else
38 OCTET_STRING_decode_uper,
39 OCTET_STRING_encode_uper,
40#endif /* ASN_DISABLE_PER_SUPPORT */
Lev Walkina5972be2017-09-29 23:15:58 -070041 RELATIVE_OID_random_fill,
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +080042 0 /* Use generic outmost tag fetcher */
43};
44asn_TYPE_descriptor_t asn_DEF_RELATIVE_OID = {
45 "RELATIVE-OID",
46 "RELATIVE_OID",
47 &asn_OP_RELATIVE_OID,
Lev Walkin5e033762004-09-29 13:26:15 +000048 asn_DEF_RELATIVE_OID_tags,
49 sizeof(asn_DEF_RELATIVE_OID_tags)
50 / sizeof(asn_DEF_RELATIVE_OID_tags[0]),
51 asn_DEF_RELATIVE_OID_tags, /* Same as above */
52 sizeof(asn_DEF_RELATIVE_OID_tags)
53 / sizeof(asn_DEF_RELATIVE_OID_tags[0]),
Lev Walkina5972be2017-09-29 23:15:58 -070054 { 0, 0, asn_generic_no_constraint },
Lev Walkin449f8322004-08-20 13:23:42 +000055 0, 0, /* No members */
Lev Walkind9bd7752004-06-05 08:17:50 +000056 0 /* No specifics */
Lev Walkinf15320b2004-06-03 03:38:44 +000057};
58
Lev Walkina9cc46e2004-09-22 16:06:28 +000059static ssize_t
60RELATIVE_OID__dump_body(const RELATIVE_OID_t *st, asn_app_consume_bytes_f *cb, void *app_key) {
61 ssize_t wrote = 0;
62 ssize_t ret;
Lev Walkin494fb702017-08-07 20:07:00 -070063 size_t startn;
64 size_t i;
Lev Walkina9cc46e2004-09-22 16:06:28 +000065
66 for(i = 0, startn = 0; i < st->size; i++) {
67 uint8_t b = st->buf[i];
68 if((b & 0x80)) /* Continuation expected */
69 continue;
70 if(startn) {
71 /* Separate arcs */
72 if(cb(".", 1, app_key) < 0)
73 return -1;
74 wrote++;
75 }
76
77 ret = OBJECT_IDENTIFIER__dump_arc(&st->buf[startn],
78 i - startn + 1, 0, cb, app_key);
79 if(ret < 0) return -1;
80 wrote += ret;
81
82 startn = i + 1;
83 }
84
85 return wrote;
86}
87
Lev Walkinf15320b2004-06-03 03:38:44 +000088int
Lev Walkin5e033762004-09-29 13:26:15 +000089RELATIVE_OID_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
Lev Walkinf15320b2004-06-03 03:38:44 +000090 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkinc2346572004-08-11 09:07:36 +000091 const RELATIVE_OID_t *st = (const RELATIVE_OID_t *)sptr;
Lev Walkinf15320b2004-06-03 03:38:44 +000092
Lev Walkind9bd7752004-06-05 08:17:50 +000093 (void)td; /* Unused argument */
94 (void)ilevel; /* Unused argument */
95
Lev Walkinf15320b2004-06-03 03:38:44 +000096 if(!st || !st->buf)
Lev Walkin8e8078a2004-09-26 13:10:40 +000097 return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
Lev Walkinf15320b2004-06-03 03:38:44 +000098
99 /* Dump preamble */
Lev Walkin8e8078a2004-09-26 13:10:40 +0000100 if(cb("{ ", 2, app_key) < 0)
Lev Walkinf15320b2004-06-03 03:38:44 +0000101 return -1;
102
Lev Walkina9cc46e2004-09-22 16:06:28 +0000103 if(RELATIVE_OID__dump_body(st, cb, app_key) < 0)
104 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000105
Lev Walkin8e8078a2004-09-26 13:10:40 +0000106 return (cb(" }", 2, app_key) < 0) ? -1 : 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000107}
108
Lev Walkin0fab1a62005-03-09 22:19:25 +0000109static enum xer_pbd_rval
110RELATIVE_OID__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) {
Lev Walkin92302252004-10-23 10:16:51 +0000111 RELATIVE_OID_t *st = (RELATIVE_OID_t *)sptr;
Lev Walkin2c34aad2005-03-10 11:50:24 +0000112 const char *chunk_end = (const char *)chunk_buf + chunk_size;
113 const char *endptr;
Lev Walkin92302252004-10-23 10:16:51 +0000114 long s_arcs[6];
115 long *arcs = s_arcs;
116 int arcs_count;
117 int ret;
118
Lev Walkine0b56e02005-02-25 12:10:27 +0000119 (void)td;
120
Lev Walkin92302252004-10-23 10:16:51 +0000121 arcs_count = OBJECT_IDENTIFIER_parse_arcs(
122 (const char *)chunk_buf, chunk_size,
Lev Walkin0fab1a62005-03-09 22:19:25 +0000123 arcs, sizeof(s_arcs)/sizeof(s_arcs[0]), &endptr);
124 if(arcs_count < 0) {
Lev Walkinaed43c82012-09-04 14:56:27 -0700125 /* Expecting at least one arc arcs */
Lev Walkin0fab1a62005-03-09 22:19:25 +0000126 return XPBD_BROKEN_ENCODING;
Lev Walkinaed43c82012-09-04 14:56:27 -0700127 } else if(arcs_count == 0) {
128 return XPBD_NOT_BODY_IGNORE;
Lev Walkin0fab1a62005-03-09 22:19:25 +0000129 }
Lev Walkinaed43c82012-09-04 14:56:27 -0700130 assert(endptr == chunk_end);
Lev Walkin0fab1a62005-03-09 22:19:25 +0000131
132 if((size_t)arcs_count > sizeof(s_arcs)/sizeof(s_arcs[0])) {
Lev Walkin92302252004-10-23 10:16:51 +0000133 arcs = (long *)MALLOC(arcs_count * sizeof(long));
Lev Walkin0fab1a62005-03-09 22:19:25 +0000134 if(!arcs) return XPBD_SYSTEM_FAILURE;
Lev Walkin92302252004-10-23 10:16:51 +0000135 ret = OBJECT_IDENTIFIER_parse_arcs(
136 (const char *)chunk_buf, chunk_size,
137 arcs, arcs_count, &endptr);
138 if(ret != arcs_count)
Lev Walkin0fab1a62005-03-09 22:19:25 +0000139 return XPBD_SYSTEM_FAILURE; /* assert?.. */
Lev Walkin92302252004-10-23 10:16:51 +0000140 }
141
142 /*
143 * Convert arcs into BER representation.
144 */
145 ret = RELATIVE_OID_set_arcs(st, arcs, sizeof(*arcs), arcs_count);
Lev Walkin92302252004-10-23 10:16:51 +0000146 if(arcs != s_arcs) FREEMEM(arcs);
147
Lev Walkin2c34aad2005-03-10 11:50:24 +0000148 return ret ? XPBD_SYSTEM_FAILURE : XPBD_BODY_CONSUMED;
Lev Walkin92302252004-10-23 10:16:51 +0000149}
150
151asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -0700152RELATIVE_OID_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
Lev Walkin92302252004-10-23 10:16:51 +0000153 asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
Lev Walkin8c3b8542005-03-10 18:52:02 +0000154 const void *buf_ptr, size_t size) {
Lev Walkin92302252004-10-23 10:16:51 +0000155
156 return xer_decode_primitive(opt_codec_ctx, td,
157 sptr, sizeof(RELATIVE_OID_t), opt_mname,
158 buf_ptr, size, RELATIVE_OID__xer_body_decode);
159}
160
Lev Walkina9cc46e2004-09-22 16:06:28 +0000161asn_enc_rval_t
Lev Walkin5e033762004-09-29 13:26:15 +0000162RELATIVE_OID_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
Lev Walkina9cc46e2004-09-22 16:06:28 +0000163 int ilevel, enum xer_encoder_flags_e flags,
164 asn_app_consume_bytes_f *cb, void *app_key) {
165 RELATIVE_OID_t *st = (RELATIVE_OID_t *)sptr;
166 asn_enc_rval_t er;
167
168 (void)ilevel; /* Unused argument */
169 (void)flags; /* Unused argument */
170
171 if(!st || !st->buf)
Lev Walkin7c1dc052016-03-14 03:08:15 -0700172 ASN__ENCODE_FAILED;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000173
174 er.encoded = RELATIVE_OID__dump_body(st, cb, app_key);
Lev Walkin7c1dc052016-03-14 03:08:15 -0700175 if(er.encoded < 0) ASN__ENCODE_FAILED;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000176
Lev Walkin7c1dc052016-03-14 03:08:15 -0700177 ASN__ENCODED_OK(er);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000178}
Lev Walkinf15320b2004-06-03 03:38:44 +0000179
180int
Wim Lewis14e6b162014-07-23 16:06:01 -0700181RELATIVE_OID_get_arcs(const RELATIVE_OID_t *roid,
Lev Walkin29a044b2004-06-14 07:24:36 +0000182 void *arcs, unsigned int arc_type_size, unsigned int arc_slots) {
Lev Walkin4d9528c2004-08-11 08:10:13 +0000183 void *arcs_end = (char *)arcs + (arc_slots * arc_type_size);
Lev Walkin29a044b2004-06-14 07:24:36 +0000184 int num_arcs = 0;
Lev Walkin494fb702017-08-07 20:07:00 -0700185 size_t startn = 0;
186 size_t i;
Lev Walkinf15320b2004-06-03 03:38:44 +0000187
188 if(!roid || !roid->buf) {
189 errno = EINVAL;
190 return -1;
191 }
192
193 for(i = 0; i < roid->size; i++) {
194 uint8_t b = roid->buf[i];
195 if((b & 0x80)) /* Continuation expected */
196 continue;
197
Lev Walkin29a044b2004-06-14 07:24:36 +0000198 if(arcs < arcs_end) {
199 if(OBJECT_IDENTIFIER_get_single_arc(
200 &roid->buf[startn],
201 i - startn + 1, 0,
202 arcs, arc_type_size))
Lev Walkinf15320b2004-06-03 03:38:44 +0000203 return -1;
Lev Walkin4ce78ca2004-08-25 01:34:11 +0000204 arcs = ((char *)arcs) + arc_type_size;
Lev Walkin29a044b2004-06-14 07:24:36 +0000205 num_arcs++;
Lev Walkinf15320b2004-06-03 03:38:44 +0000206 }
207
208 startn = i + 1;
209 }
210
Lev Walkin29a044b2004-06-14 07:24:36 +0000211 return num_arcs;
Lev Walkinf15320b2004-06-03 03:38:44 +0000212}
213
214int
Lev Walkin0787ff02004-06-17 23:43:39 +0000215RELATIVE_OID_set_arcs(RELATIVE_OID_t *roid, void *arcs, unsigned int arc_type_size, unsigned int arcs_slots) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000216 uint8_t *buf;
217 uint8_t *bp;
Lev Walkin34b2a932004-06-17 23:46:45 +0000218 unsigned int size;
219 unsigned int i;
Lev Walkinf15320b2004-06-03 03:38:44 +0000220
Lev Walkin0787ff02004-06-17 23:43:39 +0000221 if(roid == NULL || arcs == NULL || arc_type_size < 1) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000222 errno = EINVAL;
223 return -1;
224 }
225
226 /*
227 * Roughly estimate the maximum size necessary to encode these arcs.
228 */
Lev Walkin0787ff02004-06-17 23:43:39 +0000229 size = ((arc_type_size * CHAR_BIT + 6) / 7) * arcs_slots;
Lev Walkinc2346572004-08-11 09:07:36 +0000230 bp = buf = (uint8_t *)MALLOC(size + 1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000231 if(!buf) {
232 /* ENOMEM */
233 return -1;
234 }
235
236 /*
Lev Walkin0787ff02004-06-17 23:43:39 +0000237 * Encode the arcs.
Lev Walkinf15320b2004-06-03 03:38:44 +0000238 */
Lev Walkin4ce78ca2004-08-25 01:34:11 +0000239 for(i = 0; i < arcs_slots; i++, arcs = ((char *)arcs) + arc_type_size) {
Lev Walkin0787ff02004-06-17 23:43:39 +0000240 bp += OBJECT_IDENTIFIER_set_single_arc(bp,
241 arcs, arc_type_size, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000242 }
243
Lev Walkin34b2a932004-06-17 23:46:45 +0000244 assert((unsigned)(bp - buf) <= size);
Lev Walkin0787ff02004-06-17 23:43:39 +0000245
Lev Walkinf15320b2004-06-03 03:38:44 +0000246 /*
247 * Replace buffer.
248 */
Lev Walkin4efbfb72005-02-25 14:20:30 +0000249 roid->size = (int)(bp - buf);
Lev Walkinf15320b2004-06-03 03:38:44 +0000250 bp = roid->buf;
251 roid->buf = buf;
252 if(bp) FREEMEM(bp);
253
254 return 0;
255}
Lev Walkin0787ff02004-06-17 23:43:39 +0000256
Lev Walkina5972be2017-09-29 23:15:58 -0700257
258/*
259 * Generate values from the list of interesting values, or just a random value.
260 */
261static uint32_t
262RELATIVE_OID__biased_random_arc() {
263 static const uint16_t values[] = {0, 1, 127, 128, 129, 254, 255, 256};
264
Lev Walkinb5b524b2017-10-13 03:14:03 -0700265 switch(asn_random_between(0, 2)) {
266 case 0:
267 return values[asn_random_between(
268 0, sizeof(values) / sizeof(values[0]) - 1)];
269 case 1:
270 return asn_random_between(0, UINT_MAX);
271 case 2:
272 default:
273 return UINT_MAX;
Lev Walkina5972be2017-09-29 23:15:58 -0700274 }
Lev Walkina5972be2017-09-29 23:15:58 -0700275}
276
277asn_random_fill_result_t
278RELATIVE_OID_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
279 const asn_encoding_constraints_t *constraints,
280 size_t max_length) {
281 asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
282 asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
283 asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
284 RELATIVE_OID_t *st;
Lev Walkinb5b524b2017-10-13 03:14:03 -0700285 const int min_arcs = 1; /* A minimum of 1 arc is required */
286 size_t arcs_len = asn_random_between(min_arcs, 3);
Lev Walkina5972be2017-09-29 23:15:58 -0700287 uint32_t arcs[3];
Lev Walkina5972be2017-09-29 23:15:58 -0700288 size_t i;
289
290 (void)constraints;
291
292 if(max_length < arcs_len) return result_skipped;
293
294 if(*sptr) {
295 st = *sptr;
296 } else {
297 st = CALLOC(1, sizeof(*st));
298 }
299
300 for(i = 0; i < arcs_len; i++) {
301 arcs[i] = RELATIVE_OID__biased_random_arc();
302 }
303
304 if(RELATIVE_OID_set_arcs(st, arcs, sizeof(arcs[0]), arcs_len)) {
305 if(st != *sptr) {
306 ASN_STRUCT_FREE(*td, st);
307 }
308 return result_failed;
309 }
310
311 *sptr = st;
312
313 return result_ok;
314}