blob: 5d1e1a9d0b246b5365bc5e4b51a85e39e8a56fa1 [file] [log] [blame]
Lev Walkinf15320b2004-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 */
Lev Walkina9cc46e2004-09-22 16:06:28 +00005#include <asn_internal.h>
Lev Walkinf15320b2004-06-03 03:38:44 +00006#include <RELATIVE-OID.h>
Lev Walkin0787ff02004-06-17 23:43:39 +00007#include <limits.h> /* for CHAR_BIT */
Lev Walkinf15320b2004-06-03 03:38:44 +00008#include <assert.h>
9#include <errno.h>
10
11/*
12 * RELATIVE-OID basic type description.
13 */
14static ber_tlv_tag_t asn1_DEF_RELATIVE_OID_tags[] = {
15 (ASN_TAG_CLASS_UNIVERSAL | (13 << 2))
16};
17asn1_TYPE_descriptor_t asn1_DEF_RELATIVE_OID = {
18 "RELATIVE-OID",
Lev Walkina9cc46e2004-09-22 16:06:28 +000019 INTEGER_free,
20 RELATIVE_OID_print,
Lev Walkinf15320b2004-06-03 03:38:44 +000021 asn_generic_no_constraint,
22 INTEGER_decode_ber, /* Implemented in terms of INTEGER type */
23 OBJECT_IDENTIFIER_encode_der,
Lev Walkina9cc46e2004-09-22 16:06:28 +000024 0, /* Not implemented yet */
25 RELATIVE_OID_encode_xer,
Lev Walkinf15320b2004-06-03 03:38:44 +000026 0, /* Use generic outmost tag fetcher */
27 asn1_DEF_RELATIVE_OID_tags,
28 sizeof(asn1_DEF_RELATIVE_OID_tags)
29 / sizeof(asn1_DEF_RELATIVE_OID_tags[0]),
Lev Walkin188ed2c2004-09-13 08:31:01 +000030 asn1_DEF_RELATIVE_OID_tags, /* Same as above */
31 sizeof(asn1_DEF_RELATIVE_OID_tags)
32 / sizeof(asn1_DEF_RELATIVE_OID_tags[0]),
Lev Walkind9bd7752004-06-05 08:17:50 +000033 0, /* Always in primitive form */
Lev Walkin449f8322004-08-20 13:23:42 +000034 0, 0, /* No members */
Lev Walkind9bd7752004-06-05 08:17:50 +000035 0 /* No specifics */
Lev Walkinf15320b2004-06-03 03:38:44 +000036};
37
Lev Walkina9cc46e2004-09-22 16:06:28 +000038static ssize_t
39RELATIVE_OID__dump_body(const RELATIVE_OID_t *st, asn_app_consume_bytes_f *cb, void *app_key) {
40 ssize_t wrote = 0;
41 ssize_t ret;
42 int startn;
43 int i;
44
45 for(i = 0, startn = 0; i < st->size; i++) {
46 uint8_t b = st->buf[i];
47 if((b & 0x80)) /* Continuation expected */
48 continue;
49 if(startn) {
50 /* Separate arcs */
51 if(cb(".", 1, app_key) < 0)
52 return -1;
53 wrote++;
54 }
55
56 ret = OBJECT_IDENTIFIER__dump_arc(&st->buf[startn],
57 i - startn + 1, 0, cb, app_key);
58 if(ret < 0) return -1;
59 wrote += ret;
60
61 startn = i + 1;
62 }
63
64 return wrote;
65}
66
Lev Walkinf15320b2004-06-03 03:38:44 +000067int
68RELATIVE_OID_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
69 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkinc2346572004-08-11 09:07:36 +000070 const RELATIVE_OID_t *st = (const RELATIVE_OID_t *)sptr;
Lev Walkinf15320b2004-06-03 03:38:44 +000071
Lev Walkind9bd7752004-06-05 08:17:50 +000072 (void)td; /* Unused argument */
73 (void)ilevel; /* Unused argument */
74
Lev Walkinf15320b2004-06-03 03:38:44 +000075 if(!st || !st->buf)
76 return cb("<absent>", 8, app_key);
77
78 /* Dump preamble */
79 if(cb("{ ", 2, app_key))
80 return -1;
81
Lev Walkina9cc46e2004-09-22 16:06:28 +000082 if(RELATIVE_OID__dump_body(st, cb, app_key) < 0)
83 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +000084
85 return cb(" }", 2, app_key);
86}
87
Lev Walkina9cc46e2004-09-22 16:06:28 +000088asn_enc_rval_t
89RELATIVE_OID_encode_xer(asn1_TYPE_descriptor_t *td, void *sptr,
90 int ilevel, enum xer_encoder_flags_e flags,
91 asn_app_consume_bytes_f *cb, void *app_key) {
92 RELATIVE_OID_t *st = (RELATIVE_OID_t *)sptr;
93 asn_enc_rval_t er;
94
95 (void)ilevel; /* Unused argument */
96 (void)flags; /* Unused argument */
97
98 if(!st || !st->buf)
99 _ASN_ENCODE_FAILED;
100
101 er.encoded = RELATIVE_OID__dump_body(st, cb, app_key);
102 if(er.encoded < 0) _ASN_ENCODE_FAILED;
103
104 return er;
105}
Lev Walkinf15320b2004-06-03 03:38:44 +0000106
107int
Lev Walkin29a044b2004-06-14 07:24:36 +0000108RELATIVE_OID_get_arcs(RELATIVE_OID_t *roid,
109 void *arcs, unsigned int arc_type_size, unsigned int arc_slots) {
Lev Walkin4d9528c2004-08-11 08:10:13 +0000110 void *arcs_end = (char *)arcs + (arc_slots * arc_type_size);
Lev Walkin29a044b2004-06-14 07:24:36 +0000111 int num_arcs = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000112 int startn = 0;
113 int i;
114
115 if(!roid || !roid->buf) {
116 errno = EINVAL;
117 return -1;
118 }
119
120 for(i = 0; i < roid->size; i++) {
121 uint8_t b = roid->buf[i];
122 if((b & 0x80)) /* Continuation expected */
123 continue;
124
Lev Walkin29a044b2004-06-14 07:24:36 +0000125 if(arcs < arcs_end) {
126 if(OBJECT_IDENTIFIER_get_single_arc(
127 &roid->buf[startn],
128 i - startn + 1, 0,
129 arcs, arc_type_size))
Lev Walkinf15320b2004-06-03 03:38:44 +0000130 return -1;
Lev Walkin4ce78ca2004-08-25 01:34:11 +0000131 arcs = ((char *)arcs) + arc_type_size;
Lev Walkin29a044b2004-06-14 07:24:36 +0000132 num_arcs++;
Lev Walkinf15320b2004-06-03 03:38:44 +0000133 }
134
135 startn = i + 1;
136 }
137
Lev Walkin29a044b2004-06-14 07:24:36 +0000138 return num_arcs;
Lev Walkinf15320b2004-06-03 03:38:44 +0000139}
140
141int
Lev Walkin0787ff02004-06-17 23:43:39 +0000142RELATIVE_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 +0000143 uint8_t *buf;
144 uint8_t *bp;
Lev Walkin34b2a932004-06-17 23:46:45 +0000145 unsigned int size;
146 unsigned int i;
Lev Walkinf15320b2004-06-03 03:38:44 +0000147
Lev Walkin0787ff02004-06-17 23:43:39 +0000148 if(roid == NULL || arcs == NULL || arc_type_size < 1) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000149 errno = EINVAL;
150 return -1;
151 }
152
153 /*
154 * Roughly estimate the maximum size necessary to encode these arcs.
155 */
Lev Walkin0787ff02004-06-17 23:43:39 +0000156 size = ((arc_type_size * CHAR_BIT + 6) / 7) * arcs_slots;
Lev Walkinc2346572004-08-11 09:07:36 +0000157 bp = buf = (uint8_t *)MALLOC(size + 1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000158 if(!buf) {
159 /* ENOMEM */
160 return -1;
161 }
162
163 /*
Lev Walkin0787ff02004-06-17 23:43:39 +0000164 * Encode the arcs.
Lev Walkinf15320b2004-06-03 03:38:44 +0000165 */
Lev Walkin4ce78ca2004-08-25 01:34:11 +0000166 for(i = 0; i < arcs_slots; i++, arcs = ((char *)arcs) + arc_type_size) {
Lev Walkin0787ff02004-06-17 23:43:39 +0000167 bp += OBJECT_IDENTIFIER_set_single_arc(bp,
168 arcs, arc_type_size, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000169 }
170
Lev Walkin34b2a932004-06-17 23:46:45 +0000171 assert((unsigned)(bp - buf) <= size);
Lev Walkin0787ff02004-06-17 23:43:39 +0000172
Lev Walkinf15320b2004-06-03 03:38:44 +0000173 /*
174 * Replace buffer.
175 */
Lev Walkin0787ff02004-06-17 23:43:39 +0000176 roid->size = bp - buf;
Lev Walkinf15320b2004-06-03 03:38:44 +0000177 bp = roid->buf;
178 roid->buf = buf;
179 if(bp) FREEMEM(bp);
180
181 return 0;
182}
Lev Walkin0787ff02004-06-17 23:43:39 +0000183