ISSUE ID:- RICAPP-216
[ric-app/bouncer.git] / Bouncer / e2sm_kpm / lib / RELATIVE-OID.c
1 /*-
2  * Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>.
3  *      All rights reserved.
4  * Redistribution and modifications are permitted subject to BSD license.
5  */
6 #include <asn_internal.h>
7 #include <RELATIVE-OID.h>
8 #include <OCTET_STRING.h>
9 #include <asn_codecs_prim.h>    /* Encoder and decoder of a primitive type */
10 #include <limits.h>     /* for CHAR_BIT */
11 #include <errno.h>
12
13 /*
14  * RELATIVE-OID basic type description.
15  */
16 static const ber_tlv_tag_t asn_DEF_RELATIVE_OID_tags[] = {
17         (ASN_TAG_CLASS_UNIVERSAL | (13 << 2))
18 };
19 asn_TYPE_operation_t asn_OP_RELATIVE_OID = {
20         ASN__PRIMITIVE_TYPE_free,
21         RELATIVE_OID_print,
22         OCTET_STRING_compare,   /* Implemented in terms of opaque comparison */
23         ber_decode_primitive,
24         der_encode_primitive,
25         RELATIVE_OID_decode_xer,
26         RELATIVE_OID_encode_xer,
27 #ifdef  ASN_DISABLE_OER_SUPPORT
28         0,
29         0,
30 #else
31         RELATIVE_OID_decode_oer,
32         RELATIVE_OID_encode_oer,
33 #endif  /* ASN_DISABLE_OER_SUPPORT */
34 #ifdef  ASN_DISABLE_PER_SUPPORT
35         0,
36         0,
37         0,
38         0,
39 #else
40         OCTET_STRING_decode_uper,
41         OCTET_STRING_encode_uper,
42         OCTET_STRING_decode_aper,
43         OCTET_STRING_encode_aper,
44 #endif  /* ASN_DISABLE_PER_SUPPORT */
45         RELATIVE_OID_random_fill,
46         0       /* Use generic outmost tag fetcher */
47 };
48 asn_TYPE_descriptor_t asn_DEF_RELATIVE_OID = {
49         "RELATIVE-OID",
50         "RELATIVE_OID",
51         &asn_OP_RELATIVE_OID,
52         asn_DEF_RELATIVE_OID_tags,
53         sizeof(asn_DEF_RELATIVE_OID_tags)
54             / sizeof(asn_DEF_RELATIVE_OID_tags[0]),
55         asn_DEF_RELATIVE_OID_tags,      /* Same as above */
56         sizeof(asn_DEF_RELATIVE_OID_tags)
57             / sizeof(asn_DEF_RELATIVE_OID_tags[0]),
58         { 0, 0, asn_generic_no_constraint },
59         0, 0,   /* No members */
60         0       /* No specifics */
61 };
62
63 static ssize_t
64 RELATIVE_OID__dump_body(const RELATIVE_OID_t *st, asn_app_consume_bytes_f *cb, void *app_key) {
65     char scratch[32];
66     size_t produced = 0;
67     size_t off = 0;
68
69     for(;;) {
70         asn_oid_arc_t arc;
71         ssize_t rd = OBJECT_IDENTIFIER_get_single_arc(st->buf + off,
72                                                       st->size - off, &arc);
73         if(rd < 0) {
74             return -1;
75         } else if(rd == 0) {
76             /* No more arcs. */
77             break;
78         } else {
79             int ret = snprintf(scratch, sizeof(scratch), "%s%" PRIu32,
80                                off ? "." : "", arc);
81             if(ret >= (ssize_t)sizeof(scratch)) {
82                 return -1;
83             }
84             produced += ret;
85             off += rd;
86             assert(off <= st->size);
87             if(cb(scratch, ret, app_key) < 0) return -1;
88         }
89     }
90
91     if(off != st->size) {
92         ASN_DEBUG("Could not scan to the end of Object Identifier");
93         return -1;
94     }
95
96         return produced;
97 }
98
99 int
100 RELATIVE_OID_print(const asn_TYPE_descriptor_t *td, const void *sptr,
101                    int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
102     const RELATIVE_OID_t *st = (const RELATIVE_OID_t *)sptr;
103
104         (void)td;       /* Unused argument */
105         (void)ilevel;   /* Unused argument */
106
107         if(!st || !st->buf)
108                 return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
109
110         /* Dump preamble */
111         if(cb("{ ", 2, app_key) < 0)
112                 return -1;
113
114         if(RELATIVE_OID__dump_body(st, cb, app_key) < 0)
115                 return -1;
116
117         return (cb(" }", 2, app_key) < 0) ? -1 : 0;
118 }
119
120 static enum xer_pbd_rval
121 RELATIVE_OID__xer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
122                               const void *chunk_buf, size_t chunk_size) {
123     RELATIVE_OID_t *st = (RELATIVE_OID_t *)sptr;
124         const char *chunk_end = (const char *)chunk_buf + chunk_size;
125         const char *endptr;
126         asn_oid_arc_t s_arcs[6];
127         asn_oid_arc_t *arcs = s_arcs;
128         ssize_t num_arcs;
129         int ret;
130
131         (void)td;
132
133     num_arcs = OBJECT_IDENTIFIER_parse_arcs(
134         (const char *)chunk_buf, chunk_size, arcs,
135         sizeof(s_arcs) / sizeof(s_arcs[0]), &endptr);
136     if(num_arcs < 0) {
137         /* Expecting at least one arc arcs */
138         return XPBD_BROKEN_ENCODING;
139     } else if(num_arcs == 0) {
140         return XPBD_NOT_BODY_IGNORE;
141     }
142     assert(endptr == chunk_end);
143
144     if((size_t)num_arcs > sizeof(s_arcs) / sizeof(s_arcs[0])) {
145         arcs = (asn_oid_arc_t *)MALLOC(num_arcs * sizeof(arcs[0]));
146         if(!arcs) return XPBD_SYSTEM_FAILURE;
147         ret = OBJECT_IDENTIFIER_parse_arcs((const char *)chunk_buf, chunk_size,
148                                            arcs, num_arcs, &endptr);
149         if(ret != num_arcs) {
150             return XPBD_SYSTEM_FAILURE; /* assert?.. */
151         }
152     }
153
154     /*
155      * Convert arcs into BER representation.
156      */
157     ret = RELATIVE_OID_set_arcs(st, arcs, num_arcs);
158     if(arcs != s_arcs) FREEMEM(arcs);
159
160     return ret ? XPBD_SYSTEM_FAILURE : XPBD_BODY_CONSUMED;
161 }
162
163 asn_dec_rval_t
164 RELATIVE_OID_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
165                         const asn_TYPE_descriptor_t *td, void **sptr,
166                         const char *opt_mname, const void *buf_ptr,
167                         size_t size) {
168     return xer_decode_primitive(opt_codec_ctx, td,
169                 sptr, sizeof(RELATIVE_OID_t), opt_mname,
170                         buf_ptr, size, RELATIVE_OID__xer_body_decode);
171 }
172
173 asn_enc_rval_t
174 RELATIVE_OID_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
175                         int ilevel, enum xer_encoder_flags_e flags,
176                         asn_app_consume_bytes_f *cb, void *app_key) {
177         const RELATIVE_OID_t *st = (const RELATIVE_OID_t *)sptr;
178         asn_enc_rval_t er = {0,0,0};
179
180         (void)ilevel;   /* Unused argument */
181         (void)flags;    /* Unused argument */
182
183         if(!st || !st->buf)
184                 ASN__ENCODE_FAILED;
185
186         er.encoded = RELATIVE_OID__dump_body(st, cb, app_key);
187         if(er.encoded < 0) ASN__ENCODE_FAILED;
188
189         ASN__ENCODED_OK(er);
190 }
191
192 ssize_t
193 RELATIVE_OID_get_arcs(const RELATIVE_OID_t *st, asn_oid_arc_t *arcs,
194                       size_t arcs_count) {
195     size_t num_arcs = 0;
196     size_t off;
197
198     if(!st || !st->buf) {
199         errno = EINVAL;
200         return -1;
201     }
202
203     for(off = 0;;) {
204         asn_oid_arc_t arc;
205         ssize_t rd = OBJECT_IDENTIFIER_get_single_arc(st->buf + off,
206                                                       st->size - off, &arc);
207         if(rd < 0) {
208             return -1;
209         } else if(rd == 0) {
210             /* No more arcs. */
211             break;
212         } else {
213             off += rd;
214             if(num_arcs < arcs_count) {
215                 arcs[num_arcs] = arc;
216             }
217             num_arcs++;
218         }
219     }
220
221     if(off != st->size) {
222         return -1;
223     }
224
225         return num_arcs;
226 }
227
228 int
229 RELATIVE_OID_set_arcs(RELATIVE_OID_t *st, const asn_oid_arc_t *arcs,
230                       size_t arcs_count) {
231     uint8_t *buf;
232         uint8_t *bp;
233     size_t size;
234         size_t i;
235
236         if(!st || !arcs) {
237                 errno = EINVAL;
238                 return -1;
239         }
240
241         /*
242          * Roughly estimate the maximum size necessary to encode these arcs.
243          */
244     size = ((sizeof(asn_oid_arc_t) * CHAR_BIT + 6) / 7) * arcs_count;
245     bp = buf = (uint8_t *)MALLOC(size + 1);
246         if(!buf) {
247                 /* ENOMEM */
248                 return -1;
249         }
250
251         /*
252          * Encode the arcs.
253          */
254     for(i = 0; i < arcs_count; i++) {
255         ssize_t wrote = OBJECT_IDENTIFIER_set_single_arc(bp, size, arcs[i]);
256         if(wrote <= 0) {
257             FREEMEM(buf);
258             return -1;
259         }
260         assert((size_t)wrote <= size);
261         bp += wrote;
262         size -= wrote;
263     }
264
265         /*
266          * Replace buffer.
267          */
268         st->size = bp - buf;
269         bp = st->buf;
270         st->buf = buf;
271         st->buf[st->size] = '\0';
272         if(bp) FREEMEM(bp);
273
274         return 0;
275 }
276
277
278 /*
279  * Generate values from the list of interesting values, or just a random value.
280  */
281 static asn_oid_arc_t
282 RELATIVE_OID__biased_random_arc() {
283     static const uint16_t values[] = {0, 1, 127, 128, 129, 254, 255, 256};
284
285     switch(asn_random_between(0, 2)) {
286     case 0:
287         return values[asn_random_between(
288             0, sizeof(values) / sizeof(values[0]) - 1)];
289     case 1:
290         return asn_random_between(0, UINT_MAX);
291     case 2:
292     default:
293         return UINT_MAX;
294     }
295 }
296
297 asn_random_fill_result_t
298 RELATIVE_OID_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
299                          const asn_encoding_constraints_t *constraints,
300                          size_t max_length) {
301     asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
302     asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
303     asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
304     RELATIVE_OID_t *st;
305     const int min_arcs = 1; /* A minimum of 1 arc is required */
306     asn_oid_arc_t arcs[3];
307     size_t arcs_len =
308         asn_random_between(min_arcs, sizeof(arcs) / sizeof(arcs[0]));
309     size_t i;
310
311     (void)constraints;
312
313     if(max_length < arcs_len) return result_skipped;
314
315     if(*sptr) {
316         st = *sptr;
317     } else {
318         st = CALLOC(1, sizeof(*st));
319     }
320
321     for(i = 0; i < arcs_len; i++) {
322         arcs[i] = RELATIVE_OID__biased_random_arc();
323     }
324
325     if(RELATIVE_OID_set_arcs(st, arcs, arcs_len)) {
326         if(st != *sptr) {
327             ASN_STRUCT_FREE(*td, st);
328         }
329         return result_failed;
330     }
331
332     *sptr = st;
333
334     result_ok.length = st->size;
335     return result_ok;
336 }