--- /dev/null
+/*
+ * Copyright (C) 1994, Index Data I/S
+ * All rights reserved.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Log: ber_bool.c,v $
+ * Revision 1.1 1995-02-02 16:21:51 quinn
+ * First kick.
+ *
+ */
+
+#include <stdio.h>
+#include <odr.h>
+
+
+int ber_boolean(ODR o, int *val)
+{
+ unsigned char *b = o->bp;
+ int res, len;
+
+ switch (o->direction)
+ {
+ case ODR_ENCODE:
+ if (ber_enclen(o->bp, 1, 1, 1) != 1)
+ return 0;
+ o->bp++;
+ o->left--;
+ *(o->bp++) = (unsigned char) *val;
+ fprintf(stderr, "[val=%d]\n", *val);
+ o->left--;
+ return 1;
+ case ODR_DECODE:
+ if ((res = ber_declen(b, &len)) < 0)
+ return 0;
+ if (len != 1)
+ return 0;
+ o->bp+= res;
+ o->left -= res;
+ *val = *b;
+ o->bp++;
+ o->left--;
+ fprintf(stderr, "[val=%d]\n", *val);
+ return 1;
+ case ODR_PRINT:
+ return 1;
+ default: return 0;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 1994, Index Data I/S
+ * All rights reserved.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Log: ber_int.c,v $
+ * Revision 1.1 1995-02-02 16:21:52 quinn
+ * First kick.
+ *
+ */
+
+#include <odr.h>
+#include <netinet/in.h>
+#include <string.h>
+
+static int ber_encinteger(unsigned char *buf, int val, int maxlen);
+static int ber_decinteger(unsigned char *buf, int *val);
+
+int ber_integer(ODR o, int *val)
+{
+ int res;
+
+ switch (o->direction)
+ {
+ case ODR_DECODE:
+ if ((res = ber_decinteger(o->bp, val)) <= 0)
+ return 0;
+ o->bp += res;
+ o->left -= res;
+ return 1;
+ case ODR_ENCODE:
+ if ((res = ber_encinteger(o->bp, *val, o->left)) <= 0)
+ return 0;
+ o->bp += res;
+ o->left -= res;
+ return 1;
+ case ODR_PRINT: return 1;
+ default: return 0;
+ }
+}
+
+/*
+ * Returns: number of bytes written or -1 for error (out of bounds).
+ */
+int ber_encinteger(unsigned char *buf, int val, int maxlen)
+{
+ unsigned char *b = buf, *lenpos;
+ int a, len;
+ union { int i; unsigned char c[sizeof(int)]; } tmp;
+
+ lenpos = b;
+ maxlen--;
+ b++;
+
+ tmp.i = htonl(val); /* ensure that that we're big-endian */
+ for (a = 0; a < sizeof(int) - 1; a++) /* skip superfluous octets */
+ if (!((tmp.c[a] == 0 && !(tmp.c[a+1] & 0X80)) ||
+ (tmp.c[a] == 0XFF && (tmp.c[a+1] & 0X80))))
+ break;
+ if ((len = sizeof(int) - a) > maxlen)
+ return -1;
+ memcpy(b, tmp.c + a, len);
+ b += len;
+ if (ber_enclen(lenpos, len, 1, 1) != 1)
+ return -1;
+ fprintf(stderr, "[val=%d]\n", val);
+ return b - buf;
+}
+
+/*
+ * Returns: Number of bytes read or 0 if no match, -1 if error.
+ */
+int ber_decinteger(unsigned char *buf, int *val)
+{
+ unsigned char *b = buf, fill;
+ int res, len, remains;
+ union { int i; unsigned char c[sizeof(int)]; } tmp;
+
+ if ((res = ber_declen(b, &len)) < 0)
+ return -1;
+ if (len > sizeof(int)) /* let's be reasonable, here */
+ return -1;
+ b+= res;
+
+ remains = sizeof(int) - len;
+ memcpy(tmp.c + remains, b, len);
+ if (*b & 0X80)
+ fill = 0XFF;
+ else
+ fill = 0X00;
+ memset(tmp.c, fill, remains);
+ *val = ntohl(tmp.i);
+
+ b += len;
+ fprintf(stderr, "[val=%d]\n", *val);
+ return b - buf;
+}
--- /dev/null
+#include <stdio.h>
+#include <odr.h>
+
+/*
+ * Encode BER length octets. If exact, lenlen is the exact desired
+ * encoding size, else, lenlen is the max available space. Len < 0 =
+ * Indefinite encoding.
+ * Returns: >0 success, number of bytes encoded.
+ * Returns: =0 success, indefinite start-marker set. 1 byte encoded.
+ * Returns: -1 failure, out of bounds.
+ */
+int ber_enclen(unsigned char *buf, int len, int lenlen, int exact)
+{
+ unsigned char *b = buf;
+ unsigned char octs[sizeof(int)];
+ int n = 0;
+
+ fprintf(stderr, "[len=%d]", len);
+ if (len < 0) /* Indefinite */
+ {
+ *b = 0X80;
+ fprintf(stderr, "[indefinite]");
+ return 0;
+ }
+ if (len <= 127 && (lenlen == 1 || !exact)) /* definite short form */
+ {
+ *b = len;
+ return 1;
+ }
+ if (lenlen == 1)
+ {
+ *b = 0X80;
+ return 0;
+ }
+ /* definite long form */
+ do
+ {
+ octs[n++] = len;
+ len >>= 8;
+ }
+ while (len);
+ if (n >= lenlen)
+ return -1;
+ b++;
+ if (exact)
+ while (n < --lenlen) /* pad length octets */
+ *(++b) = 0;
+ while (n--)
+ *(b++) = octs[n];
+ *buf = (b - buf - 1) | 0X80;
+ return b - buf;
+}
+
+/*
+ * Decode BER length octets. Returns number of bytes read or -1 for error.
+ * After return:
+ * len = -1 indefinite.
+ * len >= 0 Length.
+ */
+int ber_declen(unsigned char *buf, int *len)
+{
+ unsigned char *b = buf;
+ int n;
+
+ if (*b == 0X80) /* Indefinite */
+ {
+ *len = -1;
+ fprintf(stderr, "[len=%d]", *len);
+ return 1;
+ }
+ if (!(*b & 0X80)) /* Definite short form */
+ {
+ *len = (int) *b;
+ fprintf(stderr, "[len=%d]", *len);
+ return 1;
+ }
+ if (*b == 0XFF) /* reserved value */
+ return -1;
+ /* indefinite long form */
+ n = *b & 0X7F;
+ *len = 0;
+ b++;
+ while (n--)
+ {
+ *len <<= 8;
+ *len |= *(b++);
+ }
+ fprintf(stderr, "[len=%d]", *len);
+ return (b - buf);
+}
--- /dev/null
+/*
+ * Copyright (C) 1994, Index Data I/S
+ * All rights reserved.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Log: ber_null.c,v $
+ * Revision 1.1 1995-02-02 16:21:52 quinn
+ * First kick.
+ *
+ */
+
+#include <odr.h>
+
+/*
+ * BER-en/decoder for NULL type.
+ */
+int ber_null(ODR o, int *val)
+{
+ switch (o->direction)
+ {
+ case ODR_ENCODE:
+ *(o->bp++) = 0X00;
+ o->left--;
+ fprintf(stderr, "[NULL]\n");
+ return 1;
+ case ODR_DECODE:
+ if (*(o->bp++) != 0X00)
+ return 0;
+ o->left--;
+ fprintf(stderr, "[NULL]\n");
+ return 1;
+ case ODR_PRINT: return 1;
+ default: return 0;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 1994, Index Data I/S
+ * All rights reserved.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Log: ber_oct.c,v $
+ * Revision 1.1 1995-02-02 16:21:52 quinn
+ * First kick.
+ *
+ */
+
+#include <odr.h>
+
+static int more_chunks(ODR o, unsigned char *base, int len)
+{
+ if (!len)
+ return 0;
+ if (len < 0) /* indefinite length */
+ {
+ if (*o->bp == 0 && *(o->bp + 1) == 0)
+ {
+ o->bp += 2;
+ o->left -= 2;
+ return 0;
+ }
+ else
+ return 1;
+ }
+ else
+ return o->bp - base < len;
+}
+
+int ber_octetstring(ODR o, ODR_OCT *p, int cons)
+{
+ int res, len;
+ unsigned char *base, *c;
+
+ switch (o->direction)
+ {
+ case ODR_DECODE:
+ if ((res = ber_declen(o->bp, &len)) < 0)
+ return 0;
+ o->bp += res;
+ o->left -= res;
+ if (cons) /* fetch component strings */
+ {
+ base = o->bp;
+ while (more_chunks(o, base, len))
+ if (!odr_octetstring(o, &p, 0))
+ return 0;
+ return 1;
+ }
+ /* primitive octetstring */
+ if (len < 0)
+ return 0;
+ if (len == 0)
+ return 1;
+ if (len > p->size - p->len)
+ {
+ c = nalloc(o, p->size += len);
+ if (p->len)
+ memcpy(c, p->buf, p->len);
+ p->buf = c;
+ }
+ memcpy(p->buf + p->len, o->bp, len);
+ p->len += len;
+ o->bp += len;
+ o->left -= len;
+ return 1;
+ case ODR_ENCODE:
+ if ((res = ber_enclen(o->bp, p->len, 5, 0)) < 0)
+ return 0;
+ o->bp += res;
+ o->left -= res;
+ if (p->len == 0)
+ return 1;
+ if (p->len > o->left)
+ return 0;
+ memcpy(o->bp, p->buf, p->len);
+ o->bp += p->len;
+ o->left -= p->len;
+ return 1;
+ case ODR_PRINT: return 1;
+ default: return 0;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 1994, Index Data I/S
+ * All rights reserved.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Log: ber_tag.c,v $
+ * Revision 1.1 1995-02-02 16:21:53 quinn
+ * First kick.
+ *
+ */
+
+#include <stdio.h>
+#include <odr.h>
+
+/* ber_tag
+ * On encoding:
+ * if p: write tag. return 1 (success) or -1 (error).
+ * if !p: return 0.
+ * On decoding:
+ * if tag && class match up, advance pointer and return 1. set cons.
+ * else leave pointer unchanged. Return 0.
+*/
+int ber_tag(ODR o, const void *p, int class, int tag, int *constructed)
+{
+ static int lclass = -1, ltag, br, lcons; /* save t&c rather than
+ decoding twice */
+ int rd;
+
+ o->t_class = -1;
+ switch (o->direction)
+ {
+ case ODR_ENCODE:
+ if (!p)
+ return 0;
+ if ((rd = ber_enctag(o->bp, class, tag, *constructed, o->left))
+ <=0)
+ return -1;
+ o->bp += rd;
+ o->left -= rd;
+ fprintf(stderr, "[class=%d,tag=%d,cons=%d]", class, tag,
+ *constructed);
+ return 1;
+ case ODR_DECODE:
+ if (lclass < 0)
+ {
+ if ((br = ber_dectag(o->bp, &lclass, <ag, &lcons)) <= 0)
+ return -1;
+ fprintf(stderr, "[class=%d,tag=%d,cons=%d]", lclass, ltag,
+ lcons);
+ }
+ if (class == lclass && tag == ltag)
+ {
+ o->bp += br;
+ o->left -= br;
+ *constructed = lcons;
+ lclass = -1;
+ return 1;
+ }
+ else
+ return 0;
+ case ODR_PRINT: return p != 0;
+ default: return 0;
+ }
+}
+
+/* ber_enctag
+ * BER-encode a class/tag/constructed package (identifier octets). Return
+ * number of bytes encoded, or -1 if out of bounds.
+ */
+int ber_enctag(unsigned char *buf, int class, int tag, int constructed, int len)
+{
+ int cons = (constructed ? 1 : 0), n = 0;
+ unsigned char octs[sizeof(int)], *b = buf;
+
+ *b = (class << 6) & 0XC0;
+ *b |= (cons << 5) & 0X20;
+ if (tag <= 30)
+ {
+ *b |= tag & 0X1F;
+ return 1;
+ }
+ else
+ {
+ *(b++) |= 0x1F;
+ do
+ {
+ octs[n++] = tag & 0X7F;
+ tag >>= 7;
+ if (n >= len) /* bounds check */
+ return -1;
+ }
+ while (tag);
+ while (n--)
+ *(b++) = octs[n] | ((n > 0) << 7);
+ return b - buf;
+ }
+}
+
+/* ber_dectag
+ * Decode BER identifier octets. Return number of bytes read or -1 for error.
+ */
+int ber_dectag(unsigned char *buf, int *class, int *tag, int *constructed)
+{
+ unsigned char *b = buf;
+
+ *class = *b >> 6;
+ *constructed = (*b >> 5) & 0X01;
+ if ((*tag = *b & 0x1F) <= 30)
+ return 1;
+ b++;
+ *tag = 0;
+ do
+ {
+ *tag <<= 7;
+ *tag |= *b & 0X7F;
+ if (b - buf >= 5) /* Precaution */
+ return -1;
+ }
+ while (*(b++) & 0X80);
+ return b - buf;
+}
--- /dev/null
+/*
+ * Copyright (C) 1994, Index Data I/S
+ * All rights reserved.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Log: odr_bool.c,v $
+ * Revision 1.1 1995-02-02 16:21:53 quinn
+ * First kick.
+ *
+ */
+
+#include <stdio.h>
+#include <odr.h>
+
+/*
+ * Top level boolean en/decoder.
+ * Returns 1 on success, 0 on error.
+ */
+int odr_bool(ODR o, int **p, int opt)
+{
+ int res, cons = 0;
+
+ if (o->t_class < 0)
+ {
+ o->t_class = ODR_UNIVERSAL;
+ o->t_tag = ODR_BOOLEAN;
+ }
+ if ((res = ber_tag(o, *p, o->t_class, o->t_tag, &cons)) < 0)
+ return 0;
+ if (!res)
+ {
+ *p = 0;
+ return opt;
+ }
+ if (o->direction == ODR_PRINT)
+ {
+ fprintf(o->print, "%s%s\n", odr_indent(o), (**p ? "TRUE" : "FALSE"));
+ return 1;
+ }
+ if (cons)
+ return 0;
+ if (o->direction == ODR_DECODE)
+ *p = nalloc(o, sizeof(int));
+ return ber_boolean(o, *p);
+}
--- /dev/null
+/*
+ * Copyright (C) 1994, Index Data I/S
+ * All rights reserved.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Log: odr_cons.c,v $
+ * Revision 1.1 1995-02-02 16:21:53 quinn
+ * First kick.
+ *
+ */
+
+#include <odr.h>
+
+int odr_constructed_begin(ODR o, void *p, int class, int tag, int opt)
+{
+ int res;
+ int cons = 1;
+
+ if (o->direction == ODR_ENCODE && !*(char*)p)
+ return opt;
+ if (o->t_class < 0)
+ {
+ o->t_class = class;
+ o->t_tag = tag;
+ }
+ if ((res = ber_tag(o, p, o->t_class, o->t_tag, &cons)) < 0)
+ return 0;
+ if (!res || !cons)
+ return opt;
+
+ o->stack[++(o->stackp)].lenb = o->bp;
+ if (o->direction == ODR_ENCODE || o->direction == ODR_PRINT)
+ {
+ o->stack[o->stackp].lenlen = 1;
+ o->bp++;
+ o->left--;
+ }
+ else if (o->direction == ODR_DECODE)
+ {
+ if ((res = ber_declen(o->bp, &o->stack[o->stackp].len)) < 0)
+ return 0;
+ o->stack[o->stackp].lenlen = res;
+ o->bp += res;
+ o->left -= res;
+ }
+ else return 0;
+
+ o->stack[o->stackp].base = o->bp;
+ return 1;
+}
+
+int odr_constructed_end(ODR o)
+{
+ int res;
+
+ if (o->stackp < 0)
+ return 0;
+ switch (o->direction)
+ {
+ case ODR_DECODE:
+ if (o->stack[o->stackp].len < 0)
+ {
+ if (*o->bp++ == 0 && *(o->bp++) == 0)
+ {
+ o->left -= 2;
+ return 1;
+ }
+ else
+ return 0;
+ }
+ else if (o->bp - o->stack[o->stackp].base !=
+ o->stack[o->stackp].len)
+ return 0;
+ o->stackp--;
+ return 1;
+ case ODR_ENCODE:
+ if ((res = ber_enclen(o->stack[o->stackp].lenb,
+ o->bp - o->stack[o->stackp].base,
+ o->stack[o->stackp].lenlen, 1)) < 0)
+ return 0;
+ if (res == 0) /* indefinite encoding */
+ {
+ *(o->bp++) = *(o->bp++) = 0;
+ o->left--;
+ }
+ o->stackp--;
+ return 1;
+ case ODR_PRINT: return 1;
+ default: return 0;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 1994, Index Data I/S
+ * All rights reserved.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Log: odr_int.c,v $
+ * Revision 1.1 1995-02-02 16:21:53 quinn
+ * First kick.
+ *
+ */
+
+#include <odr.h>
+
+/*
+ * Top level integer en/decoder.
+ * Returns 1 on success, 0 on error.
+ */
+int odr_integer(ODR o, int **p, int opt)
+{
+ int res, cons = 0;
+
+ if (o->t_class < 0)
+ {
+ o->t_class = ODR_UNIVERSAL;
+ o->t_tag = ODR_INTEGER;
+ }
+ if ((res = ber_tag(o, *p, o->t_class, o->t_tag, &cons)) < 0)
+ return 0;
+ if (!res)
+ {
+ *p = 0;
+ return opt;
+ }
+ if (o->direction == ODR_PRINT)
+ {
+ fprintf(o->print, "%d\n", **p);
+ return 1;
+ }
+ if (cons)
+ return 0;
+ if (o->direction == ODR_DECODE)
+ *p = nalloc(o, sizeof(int));
+ return ber_integer(o, *p);
+}
--- /dev/null
+/*
+ * Copyright (C) 1994, Index Data I/S
+ * All rights reserved.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Log: odr_null.c,v $
+ * Revision 1.1 1995-02-02 16:21:54 quinn
+ * First kick.
+ *
+ */
+
+#include <odr.h>
+
+/*
+ * Top level null en/decoder.
+ * Returns 1 on success, 0 on error.
+ */
+int odr_null(ODR o, int **p, int opt)
+{
+ int res, cons = 0;
+ static int nullval = 0;
+
+ if (o->t_class < 0)
+ {
+ o->t_class = ODR_UNIVERSAL;
+ o->t_tag = ODR_NULL;
+ }
+ if ((res = ber_tag(o, *p, o->t_class, o->t_tag, &cons)) < 0)
+ return 0;
+ if (!res)
+ {
+ *p = 0;
+ return opt;
+ }
+ if (o->direction == ODR_PRINT)
+ {
+ fprintf(o->print, "NULL\n");
+ return 1;
+ }
+ if (cons)
+ return 0;
+ if (o->direction == ODR_DECODE)
+ *p = &nullval;
+ return ber_null(o, *p);
+}
--- /dev/null
+/*
+ * Copyright (C) 1994, Index Data I/S
+ * All rights reserved.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Log: odr_oct.c,v $
+ * Revision 1.1 1995-02-02 16:21:54 quinn
+ * First kick.
+ *
+ */
+
+#include <odr.h>
+
+/*
+ * Top level octet string en/decoder.
+ * Returns 1 on success, 0 on error.
+ */
+int odr_octetstring(ODR o, ODR_OCT **p, int opt)
+{
+ int res, cons = 0;
+
+ if (o->t_class < 0)
+ {
+ o->t_class = ODR_UNIVERSAL;
+ o->t_tag = ODR_OCTETSTRING;
+ }
+ if ((res = ber_tag(o, *p, o->t_class, o->t_tag, &cons)) < 0)
+ return 0;
+ if (!res)
+ {
+ *p = 0;
+ return opt;
+ }
+ if (o->direction == ODR_PRINT)
+ {
+ fprintf(o->print, "OCTETSTRING(len=%d)\n", (*p)->len);
+ return 1;
+ }
+ if (o->direction == ODR_DECODE && !*p)
+ {
+ *p = nalloc(o, sizeof(ODR_OCT));
+ (*p)->size= 0;
+ (*p)->len = 0;
+ (*p)->buf = 0;
+ }
+ return ber_octetstring(o, *p, cons);
+}
--- /dev/null
+#define ber_enclen_short(b, len) ((*(b) = (len) & 0X7F), 1)
--- /dev/null
+/*
+ * Copyright (C) 1994, Index Data I/S
+ * All rights reserved.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Log: odr_seq.c,v $
+ * Revision 1.1 1995-02-02 16:21:54 quinn
+ * First kick.
+ *
+ */
+
+#include <odr.h>
+
+int odr_sequence_begin(ODR o, void *p, int size)
+{
+ char **pp = (char**) p;
+
+ if (o->t_class < 0)
+ {
+ o->t_class = ODR_UNIVERSAL;
+ o->t_tag = ODR_SEQUENCE;
+ }
+
+ if (odr_constructed_begin(o, p, o->t_class, o->t_tag, 0))
+ {
+ if (o->direction == ODR_DECODE)
+ *pp = nalloc(o, size);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+int odr_sequence_end(ODR o)
+{
+ return odr_constructed_end(o);
+}
--- /dev/null
+/*
+ * Copyright (C) 1994, Index Data I/S
+ * All rights reserved.
+ * Sebastian Hammer, Adam Dickmeiss
+ *
+ * $Log: odr_tag.c,v $
+ * Revision 1.1 1995-02-02 16:21:54 quinn
+ * First kick.
+ *
+ */
+
+#include <odr.h>
+
+int odr_implicit_settag(ODR o, int class, int tag)
+{
+ if (o->t_class < 0)
+ {
+ o->t_class = class;
+ o->t_tag = tag;
+ }
+ return 1;
+}
--- /dev/null
+#include <odr.h>
+#include <stdlib.h>
+
+void *nalloc(ODR o, int size) { return malloc(size); }
+char *odr_indent(ODR o) {return "";}
--- /dev/null
+#include <stdio.h>
+
+#include <odr.h>
+
+int odr_dummy(ODR o, int **p, int opt)
+{
+ return odr_implicit(o, odr_integer, p, ODR_PRIVATE, 10, opt);
+}
+
+struct dummy
+{
+ int *alfa;
+ int *beta;
+};
+
+int odr_dummy2(ODR o, struct dummy **p, int opt)
+{
+ struct dummy *pp;
+
+ if (!odr_sequence_begin(o, p, sizeof(**p)))
+ return opt;
+ pp = *p;
+ return
+ odr_implicit(o, odr_integer, &pp->alfa, ODR_CONTEXT, 1, 1) &&
+ odr_implicit(o, odr_integer, &pp->beta, ODR_CONTEXT, 2, 1) &&
+ odr_sequence_end(o);
+}
+
+int main()
+{
+ int i;
+ unsigned char buf[1024];
+ struct odr o;
+ int test=-99999;
+ int *tp = &test, *tp2;
+ ODR_OCT bbb, *bbb1, *bbb2;
+ ODR_OCT ccc, *ccc1;
+ char *str1 = "FOO", *str2 = "BAR";
+
+ o.buf = buf;
+ o.bp=o.buf;
+ o.left = o.buflen = 1024;
+ o.direction = ODR_ENCODE;
+ o.t_class = -1;
+
+ bbb.buf = (unsigned char *) str1;
+ bbb.len = bbb.size = strlen(str1);
+ bbb1 = &bbb;
+
+ ccc.buf = (unsigned char*) str2;
+ ccc.len = ccc.size = strlen(str2);
+ ccc1 = &ccc;
+
+ odr_constructed_begin(&o, &bbb1, ODR_UNIVERSAL, ODR_OCTETSTRING, 0);
+ odr_octetstring(&o, &bbb1, 0);
+ odr_octetstring(&o, &ccc1, 0);
+ odr_constructed_end(&o);
+
+ o.direction = ODR_DECODE;
+ o.bp = o.buf;
+
+ odr_octetstring(&o, &bbb2, 0);
+}