blob: e0c898da71882e0271491d4d1197f133df849250 [file] [log] [blame]
vlmfa67ddc2004-06-03 03:38:44 +00001/*-
2 * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
3 * Redistribution and modifications are permitted subject to BSD license.
4 */
5#include <constr_SET_OF.h>
6#include <asn_SET_OF.h>
7
8/*
9 * Number of bytes left for this structure.
10 * (ctx->left) indicates the number of bytes _transferred_ for the structure.
11 * (size) contains the number of bytes in the buffer passed.
12 */
vlmc5190612004-08-18 04:53:32 +000013#define LEFT ((size<(size_t)ctx->left)?size:(size_t)ctx->left)
vlmfa67ddc2004-06-03 03:38:44 +000014
15/*
16 * If the subprocessor function returns with an indication that it wants
17 * more data, it may well be a fatal decoding problem, because the
18 * size is constrained by the <TLV>'s L, even if the buffer size allows
19 * reading more data.
20 * For example, consider the buffer containing the following TLVs:
21 * <T:5><L:1><V> <T:6>...
22 * The TLV length clearly indicates that one byte is expected in V, but
23 * if the V processor returns with "want more data" even if the buffer
24 * contains way more data than the V processor have seen.
25 */
vlmb42843a2004-06-05 08:17:50 +000026#define SIZE_VIOLATION (ctx->left != -1 && (size_t)ctx->left <= size)
vlmfa67ddc2004-06-03 03:38:44 +000027
28/*
29 * This macro "eats" the part of the buffer which is definitely "consumed",
30 * i.e. was correctly converted into local representation or rightfully skipped.
31 */
32#define ADVANCE(num_bytes) do { \
33 size_t num = num_bytes; \
vlm1ff928d2004-08-11 08:10:13 +000034 (char *)ptr += num; \
vlmfa67ddc2004-06-03 03:38:44 +000035 size -= num; \
36 if(ctx->left >= 0) \
37 ctx->left -= num; \
38 consumed_myself += num; \
39 } while(0)
40
41/*
42 * Switch to the next phase of parsing.
43 */
44#define NEXT_PHASE(ctx) do { \
45 ctx->phase++; \
46 ctx->step = 0; \
47 } while(0)
48#define PHASE_OUT(ctx) do { ctx->phase = 10; } while(0)
49
50/*
51 * Return a standardized complex structure.
52 */
53#define RETURN(_code) do { \
54 rval.code = _code; \
55 rval.consumed = consumed_myself;\
56 return rval; \
57 } while(0)
58
59/*
60 * The decoder of the SET OF type.
61 */
62ber_dec_rval_t
vlme413c122004-08-20 13:23:42 +000063SET_OF_decode_ber(asn1_TYPE_descriptor_t *td,
vlmfa67ddc2004-06-03 03:38:44 +000064 void **struct_ptr, void *ptr, size_t size, int tag_mode) {
65 /*
66 * Bring closer parts of structure description.
67 */
vlme413c122004-08-20 13:23:42 +000068 asn1_SET_OF_specifics_t *specs = (asn1_SET_OF_specifics_t *)td->specifics;
69 asn1_TYPE_member_t *element = td->elements; /* Single one */
vlmfa67ddc2004-06-03 03:38:44 +000070
71 /*
72 * Parts of the structure being constructed.
73 */
74 void *st = *struct_ptr; /* Target structure. */
75 ber_dec_ctx_t *ctx; /* Decoder context */
76
77 ber_tlv_tag_t tlv_tag; /* T from TLV */
78 //ber_tlv_len_t tlv_len; /* L from TLV */
79 ber_dec_rval_t rval; /* Return code from subparsers */
80
81 ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
82
vlme413c122004-08-20 13:23:42 +000083 ASN_DEBUG("Decoding %s as SET OF", td->name);
vlmfa67ddc2004-06-03 03:38:44 +000084
85 /*
86 * Create the target structure if it is not present already.
87 */
88 if(st == 0) {
89 st = *struct_ptr = CALLOC(1, specs->struct_size);
90 if(st == 0) {
91 RETURN(RC_FAIL);
92 }
93 }
94
95 /*
96 * Restore parsing context.
97 */
vlm1ff928d2004-08-11 08:10:13 +000098 ctx = (ber_dec_ctx_t *)((char *)st + specs->ctx_offset);
vlmfa67ddc2004-06-03 03:38:44 +000099
100 /*
101 * Start to parse where left previously
102 */
103 switch(ctx->phase) {
104 case 0:
105 /*
106 * PHASE 0.
107 * Check that the set of tags associated with given structure
108 * perfectly fits our expectations.
109 */
110
vlme413c122004-08-20 13:23:42 +0000111 rval = ber_check_tags(td, ctx, ptr, size,
vlmfa67ddc2004-06-03 03:38:44 +0000112 tag_mode, &ctx->left, 0);
113 if(rval.code != RC_OK) {
114 ASN_DEBUG("%s tagging check failed: %d",
vlme413c122004-08-20 13:23:42 +0000115 td->name, rval.code);
vlmfa67ddc2004-06-03 03:38:44 +0000116 consumed_myself += rval.consumed;
117 RETURN(rval.code);
118 }
119
120 if(ctx->left >= 0)
121 ctx->left += rval.consumed; /* ?Substracted below! */
122 ADVANCE(rval.consumed);
123
124 ASN_DEBUG("Structure consumes %ld bytes, "
125 "buffer %ld", (long)ctx->left, (long)size);
126
127 NEXT_PHASE(ctx);
128 /* Fall through */
129 case 1:
130 /*
131 * PHASE 1.
132 * From the place where we've left it previously,
133 * try to decode the next item.
134 */
135 for(;; ctx->step = 0) {
136 ssize_t tag_len; /* Length of TLV's T */
137
138 if(ctx->step & 1)
139 goto microphase2;
140
141 /*
142 * MICROPHASE 1: Synchronize decoding.
143 */
144
145 if(ctx->left == 0) {
vlme413c122004-08-20 13:23:42 +0000146 ASN_DEBUG("End of SET OF %s", td->name);
vlmfa67ddc2004-06-03 03:38:44 +0000147 /*
148 * No more things to decode.
149 * Exit out of here.
150 */
151 PHASE_OUT(ctx);
152 RETURN(RC_OK);
153 }
154
155 /*
156 * Fetch the T from TLV.
157 */
158 tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
159 switch(tag_len) {
160 case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
161 /* Fall through */
162 case -1: RETURN(RC_FAIL);
163 }
164
165 if(ctx->left < 0 && ((uint8_t *)ptr)[0] == 0) {
166 if(LEFT < 2) {
167 if(SIZE_VIOLATION)
168 RETURN(RC_FAIL);
169 else
170 RETURN(RC_WMORE);
171 } else if(((uint8_t *)ptr)[1] == 0) {
172 /*
173 * Found the terminator of the
174 * indefinite length structure.
175 */
176 break;
177 }
178 }
179
180 /* Outmost tag may be unknown and cannot be fetched/compared */
vlmb42843a2004-06-05 08:17:50 +0000181 if(element->tag != (ber_tlv_tag_t)-1) {
vlmfa67ddc2004-06-03 03:38:44 +0000182 if(BER_TAGS_EQUAL(tlv_tag, element->tag)) {
183 /*
184 * The new list member of expected type has arrived.
185 */
186 } else {
187 ASN_DEBUG("Unexpected tag %s fixed SET OF %s",
vlme413c122004-08-20 13:23:42 +0000188 ber_tlv_tag_string(tlv_tag), td->name);
vlmfa67ddc2004-06-03 03:38:44 +0000189 ASN_DEBUG("%s SET OF has tag %s",
vlme413c122004-08-20 13:23:42 +0000190 td->name, ber_tlv_tag_string(element->tag));
vlmfa67ddc2004-06-03 03:38:44 +0000191 RETURN(RC_FAIL);
192 }
193 }
194
195 /*
196 * MICROPHASE 2: Invoke the member-specific decoder.
197 */
198 ctx->step |= 1; /* Confirm entering next microphase */
199 microphase2:
200
201 /*
202 * Invoke the member fetch routine according to member's type
203 */
vlmda674682004-08-11 09:07:36 +0000204 rval = element->type->ber_decoder(element->type,
vlmfa67ddc2004-06-03 03:38:44 +0000205 &ctx->ptr, ptr, LEFT, 0);
206 ASN_DEBUG("In %s SET OF %s code %d consumed %d",
vlme413c122004-08-20 13:23:42 +0000207 td->name, element->type->name,
vlmfa67ddc2004-06-03 03:38:44 +0000208 rval.code, (int)rval.consumed);
209 switch(rval.code) {
210 case RC_OK:
211 {
vlmda674682004-08-11 09:07:36 +0000212 A_SET_OF(void) *list;
213 (void *)list = st;
vlmfa67ddc2004-06-03 03:38:44 +0000214 if(ASN_SET_ADD(list, ctx->ptr) != 0)
215 RETURN(RC_FAIL);
216 else
217 ctx->ptr = 0;
218 }
219 break;
220 case RC_WMORE: /* More data expected */
221 if(!SIZE_VIOLATION) {
222 ADVANCE(rval.consumed);
223 RETURN(RC_WMORE);
224 }
225 /* Fall through */
226 case RC_FAIL: /* Fatal error */
227 RETURN(RC_FAIL);
228 } /* switch(rval) */
229
230 ADVANCE(rval.consumed);
231 } /* for(all list members) */
232
233 NEXT_PHASE(ctx);
234 case 2:
235 /*
236 * Read in all "end of content" TLVs.
237 */
238 while(ctx->left < 0) {
239 if(LEFT < 2) {
240 if(LEFT > 0 && ((char *)ptr)[0] != 0) {
241 /* Unexpected tag */
242 RETURN(RC_FAIL);
243 } else {
244 RETURN(RC_WMORE);
245 }
246 }
247 if(((char *)ptr)[0] == 0
248 && ((char *)ptr)[1] == 0) {
249 ADVANCE(2);
250 ctx->left++;
251 } else {
252 RETURN(RC_FAIL);
253 }
254 }
255
256 PHASE_OUT(ctx);
257 }
258
259 RETURN(RC_OK);
260}
261
262/*
263 * Internally visible buffer holding a single encoded element.
264 */
265struct _el_buffer {
266 uint8_t *buf;
267 size_t length;
268 size_t size;
269};
270/* Append bytes to the above structure */
271static int _el_addbytes(const void *buffer, size_t size, void *el_buf_ptr) {
vlmda674682004-08-11 09:07:36 +0000272 struct _el_buffer *el_buf = (struct _el_buffer *)el_buf_ptr;
vlmfa67ddc2004-06-03 03:38:44 +0000273
274 if(el_buf->length + size > el_buf->size)
275 return -1;
276
277 memcpy(el_buf->buf + el_buf->length, buffer, size);
278
279 el_buf->length += size;
280 return 0;
281}
282static int _el_buf_cmp(const void *ap, const void *bp) {
vlmda674682004-08-11 09:07:36 +0000283 const struct _el_buffer *a = (const struct _el_buffer *)ap;
284 const struct _el_buffer *b = (const struct _el_buffer *)bp;
vlmfa67ddc2004-06-03 03:38:44 +0000285 int ret;
286 size_t common_len;
287
288 if(a->length < b->length)
289 common_len = a->length;
290 else
291 common_len = b->length;
292
293 ret = memcmp(a->buf, b->buf, common_len);
294 if(ret == 0) {
295 if(a->length < b->length)
296 ret = -1;
297 else if(a->length > b->length)
298 ret = 1;
299 }
300
301 return ret;
302}
303
304/*
305 * The DER encoder of the SET OF type.
306 */
307der_enc_rval_t
vlme413c122004-08-20 13:23:42 +0000308SET_OF_encode_der(asn1_TYPE_descriptor_t *td, void *ptr,
vlmfa67ddc2004-06-03 03:38:44 +0000309 int tag_mode, ber_tlv_tag_t tag,
310 asn_app_consume_bytes_f *cb, void *app_key) {
vlme413c122004-08-20 13:23:42 +0000311 asn1_TYPE_member_t *elm = td->elements;
vlmfa67ddc2004-06-03 03:38:44 +0000312 asn1_TYPE_descriptor_t *elm_type = elm->type;
313 der_type_encoder_f *der_encoder = elm_type->der_encoder;
vlmda674682004-08-11 09:07:36 +0000314 A_SET_OF(void) *list;
vlmfa67ddc2004-06-03 03:38:44 +0000315 size_t computed_size = 0;
316 ssize_t encoding_size = 0;
317 struct _el_buffer *encoded_els;
318 size_t max_encoded_len = 1;
319 der_enc_rval_t erval;
320 int ret;
321 int edx;
322
vlme413c122004-08-20 13:23:42 +0000323 ASN_DEBUG("Estimating size for SET OF %s", td->name);
vlmfa67ddc2004-06-03 03:38:44 +0000324
325 /*
326 * Gather the length of the underlying members sequence.
327 */
vlmda674682004-08-11 09:07:36 +0000328 (void *)list = ptr;
vlmfa67ddc2004-06-03 03:38:44 +0000329 for(edx = 0; edx < list->count; edx++) {
330 void *memb_ptr = list->array[edx];
331 erval = der_encoder(elm_type, memb_ptr, 0, elm->tag, 0, 0);
332 if(erval.encoded == -1)
333 return erval;
334 computed_size += erval.encoded;
335
336 /* Compute maximum encoding's size */
vlmb42843a2004-06-05 08:17:50 +0000337 if(max_encoded_len < (size_t)erval.encoded)
vlmfa67ddc2004-06-03 03:38:44 +0000338 max_encoded_len = erval.encoded;
339 }
340
341 /*
342 * Encode the TLV for the sequence itself.
343 */
vlme413c122004-08-20 13:23:42 +0000344 encoding_size = der_write_tags(td, computed_size, tag_mode, tag,
vlmfa67ddc2004-06-03 03:38:44 +0000345 cb, app_key);
346 if(encoding_size == -1) {
347 erval.encoded = -1;
vlme413c122004-08-20 13:23:42 +0000348 erval.failed_type = td;
vlmfa67ddc2004-06-03 03:38:44 +0000349 erval.structure_ptr = ptr;
350 return erval;
351 }
352 computed_size += encoding_size;
353
354 if(!cb) {
355 erval.encoded = computed_size;
356 return erval;
357 }
358
359 /*
360 * DER mandates dynamic sorting of the SET OF elements
361 * according to their encodings. Build an array of the
362 * encoded elements.
363 */
vlmda674682004-08-11 09:07:36 +0000364 (void *)encoded_els = MALLOC(list->count * sizeof(encoded_els[0]));
vlmfa67ddc2004-06-03 03:38:44 +0000365 if(encoded_els == NULL) {
366 erval.encoded = -1;
vlme413c122004-08-20 13:23:42 +0000367 erval.failed_type = td;
vlmfa67ddc2004-06-03 03:38:44 +0000368 erval.structure_ptr = ptr;
369 return erval;
370 }
371
vlme413c122004-08-20 13:23:42 +0000372 ASN_DEBUG("Encoding members of %s SET OF", td->name);
vlmfa67ddc2004-06-03 03:38:44 +0000373
374 /*
375 * Encode all members.
376 */
377 for(edx = 0; edx < list->count; edx++) {
378 void *memb_ptr = list->array[edx];
379 struct _el_buffer *encoded_el = &encoded_els[edx];
380
381 /*
382 * Prepare space for encoding.
383 */
vlmda674682004-08-11 09:07:36 +0000384 encoded_el->buf = (uint8_t *)MALLOC(max_encoded_len);
vlmfa67ddc2004-06-03 03:38:44 +0000385 if(encoded_el->buf) {
386 encoded_el->length = 0;
387 encoded_el->size = max_encoded_len;
388 } else {
389 for(edx--; edx >= 0; edx--)
390 FREEMEM(encoded_els[edx].buf);
391 FREEMEM(encoded_els);
392 erval.encoded = -1;
vlme413c122004-08-20 13:23:42 +0000393 erval.failed_type = td;
vlmfa67ddc2004-06-03 03:38:44 +0000394 erval.structure_ptr = ptr;
395 return erval;
396 }
397
398 /*
399 * Encode the member into the prepared space.
400 */
401 erval = der_encoder(elm_type, memb_ptr, 0, elm->tag,
402 _el_addbytes, encoded_el);
403 if(erval.encoded == -1) {
404 for(; edx >= 0; edx--)
405 FREEMEM(encoded_els[edx].buf);
406 FREEMEM(encoded_els);
407 return erval;
408 }
409 encoding_size += erval.encoded;
410 }
411
412 /*
413 * Sort the encoded elements according to their encoding.
414 */
415 qsort(encoded_els, list->count, sizeof(encoded_els[0]), _el_buf_cmp);
416
417 /*
418 * Report encoded elements to the application.
419 * Dispose of temporary sorted members table.
420 */
421 ret = 0;
422 for(edx = 0; edx < list->count; edx++) {
423 struct _el_buffer *encoded_el = &encoded_els[edx];
424 /* Report encoded chunks to the application */
425 if(ret == 0
426 && cb(encoded_el->buf, encoded_el->length, app_key) == -1)
427 ret = -1;
428 FREEMEM(encoded_el->buf);
429 }
430 FREEMEM(encoded_els);
431
vlmb42843a2004-06-05 08:17:50 +0000432 if(ret || computed_size != (size_t)encoding_size) {
vlmfa67ddc2004-06-03 03:38:44 +0000433 /*
434 * Standard callback failed, or
435 * encoded size is not equal to the computed size.
436 */
437 erval.encoded = -1;
vlme413c122004-08-20 13:23:42 +0000438 erval.failed_type = td;
vlmfa67ddc2004-06-03 03:38:44 +0000439 erval.structure_ptr = ptr;
440 } else {
441 erval.encoded = computed_size;
442 }
443
444 return erval;
445}
446
447int
448SET_OF_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
449 asn_app_consume_bytes_f *cb, void *app_key) {
vlme413c122004-08-20 13:23:42 +0000450 asn1_TYPE_member_t *element = td->elements;
vlmda674682004-08-11 09:07:36 +0000451 const A_SET_OF(void) *list;
vlmfa67ddc2004-06-03 03:38:44 +0000452 int ret;
453 int i;
454
455 if(!sptr) return cb("<absent>", 8, app_key);
456
457 /* Dump preamble */
458 if(cb(td->name, strlen(td->name), app_key)
459 || cb(" ::= {\n", 7, app_key))
460 return -1;
461
vlme5174082004-08-11 09:34:42 +0000462 (const void *)list = sptr;
vlmfa67ddc2004-06-03 03:38:44 +0000463 for(i = 0; i < list->count; i++) {
464 const void *memb_ptr = list->array[i];
465 if(!memb_ptr) continue;
466
467 /* Indentation */
468 for(ret = 0; ret < ilevel; ret++) cb(" ", 1, app_key);
469
470 ret = element->type->print_struct(element->type, memb_ptr,
471 ilevel + 4, cb, app_key);
472 if(ret) return ret;
473
474 ret = cb("\n", 1, app_key);
475 if(ret) return ret;
476 }
477
478 /* Indentation */
479 for(ret = 0; ret < ilevel - 4; ret++) cb(" ", 1, app_key);
480
481 return cb("}", 1, app_key);
482}
483
484void
485SET_OF_free(asn1_TYPE_descriptor_t *td, void *ptr, int contents_only) {
486 if(td && ptr) {
vlme413c122004-08-20 13:23:42 +0000487 asn1_TYPE_member_t *element = td->elements;
vlmda674682004-08-11 09:07:36 +0000488 A_SET_OF(void) *list;
vlmfa67ddc2004-06-03 03:38:44 +0000489 int i;
490
491 /*
492 * Could not use set_of_empty() because of (*free)
493 * incompatibility.
494 */
vlmda674682004-08-11 09:07:36 +0000495 (void *)list = ptr;
vlmfa67ddc2004-06-03 03:38:44 +0000496 for(i = 0; i < list->count; i++) {
497 void *memb_ptr = list->array[i];
498 if(memb_ptr)
499 element->type->free_struct(element->type, memb_ptr, 0);
500 }
vlm7ebd67c2004-07-15 10:51:26 +0000501 list->count = 0; /* No meaningful elements left */
502
503 asn_set_empty(list); /* Remove (list->array) */
vlmfa67ddc2004-06-03 03:38:44 +0000504
505 if(!contents_only) {
506 FREEMEM(ptr);
507 }
508 }
509}
510
511int
512SET_OF_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,
513 asn_app_consume_bytes_f *app_errlog, void *app_key) {
vlme413c122004-08-20 13:23:42 +0000514 asn1_TYPE_member_t *element = td->elements;
515 asn_constr_check_f *constr;
vlmda674682004-08-11 09:07:36 +0000516 const A_SET_OF(void) *list;
vlmfa67ddc2004-06-03 03:38:44 +0000517 int i;
518
519 if(!sptr) {
vlme3f0f282004-08-11 09:44:13 +0000520 _ASN_ERRLOG(app_errlog, app_key,
vlm758530a2004-08-22 13:47:59 +0000521 "%s: value not given (%s:%d)",
522 td->name, __FILE__, __LINE__);
vlmfa67ddc2004-06-03 03:38:44 +0000523 return -1;
524 }
525
vlme5174082004-08-11 09:34:42 +0000526 (const void *)list = sptr;
vlme413c122004-08-20 13:23:42 +0000527
528 constr = element->memb_constraints;
529 if(!constr) constr = element->type->check_constraints;
530
531 /*
532 * Iterate over the members of an array.
533 * Validate each in turn, until one fails.
534 */
vlmfa67ddc2004-06-03 03:38:44 +0000535 for(i = 0; i < list->count; i++) {
536 const void *memb_ptr = list->array[i];
vlme413c122004-08-20 13:23:42 +0000537 int ret;
538
vlmfa67ddc2004-06-03 03:38:44 +0000539 if(!memb_ptr) continue;
vlme413c122004-08-20 13:23:42 +0000540
541 ret = constr(element->type, memb_ptr, app_errlog, app_key);
542 if(ret) return ret;
vlmfa67ddc2004-06-03 03:38:44 +0000543 }
544
vlme413c122004-08-20 13:23:42 +0000545 /*
546 * Cannot inherit it eralier:
547 * need to make sure we get the updated version.
548 */
549 if(!element->memb_constraints)
550 element->memb_constraints = element->type->check_constraints;
551
vlmfa67ddc2004-06-03 03:38:44 +0000552 return 0;
553}