4 * @brief Implementation of ietfAttr_t.
9 * Copyright (C) 2007 Andreas Steffen, Hochschule fuer Technik Rapperswil
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 #include <asn1/asn1.h>
27 #include <utils/lexparser.h>
29 #include "ietf_attr_list.h"
32 * Private definition of ietfAttribute kinds
35 IETF_ATTRIBUTE_OCTETS
= 0,
36 IETF_ATTRIBUTE_OID
= 1,
37 IETF_ATTRIBUTE_STRING
= 2
40 typedef struct ietfAttr_t ietfAttr_t
;
43 * Private definition of an ietfAttribute
52 * IETF attribute valuse
57 * Compares two ietfAttributes
59 * return -1 if this is earlier in the alphabet than other
60 * return 0 if this equals other
61 * return +1 if this is later in the alphabet than other
63 * @param this calling object
64 * @param other other object
66 int (*compare
) (const ietfAttr_t
*this ,const ietfAttr_t
*other
);
69 * Destroys the ietfAttr_t object.
71 * @param this ietfAttr_t to destroy
73 void (*destroy
) (ietfAttr_t
*this);
77 * Implements ietfAttr_t.compare.
79 static int ietfAttr_compare(const ietfAttr_t
*this ,const ietfAttr_t
*other
)
81 int cmp_len
, len
, cmp_value
;
83 /* OID attributes are appended after STRING and OCTETS attributes */
84 if (this->kind
!= IETF_ATTRIBUTE_OID
&& other
->kind
== IETF_ATTRIBUTE_OID
)
88 if (this->kind
== IETF_ATTRIBUTE_OID
&& other
->kind
!= IETF_ATTRIBUTE_OID
)
93 cmp_len
= this->value
.len
- other
->value
.len
;
94 len
= (cmp_len
< 0)?
this->value
.len
: other
->value
.len
;
95 cmp_value
= memcmp(this->value
.ptr
, other
->value
.ptr
, len
);
97 return (cmp_value
== 0)? cmp_len
: cmp_value
;
101 * Implements ietfAttr_t.destroy.
103 static void ietfAttr_destroy(ietfAttr_t
*this)
105 free(this->value
.ptr
);
110 * Creates an ietfAttr_t object.
112 static ietfAttr_t
*ietfAttr_create(ietfAttribute_t kind
, chunk_t value
)
114 ietfAttr_t
*this = malloc_thing(ietfAttr_t
);
118 this->value
= chunk_clone(value
);
121 this->compare
= ietfAttr_compare
;
122 this->destroy
= ietfAttr_destroy
;
128 * Adds an ietfAttr_t object to a sorted linked list
130 static void ietfAttr_add(linked_list_t
*list
, ietfAttr_t
*attr
)
132 iterator_t
*iterator
= list
->create_iterator(list
, TRUE
);
133 ietfAttr_t
*current_attr
;
136 while (iterator
->iterate(iterator
, (void **)¤t_attr
))
138 int cmp
= attr
->compare(attr
, current_attr
);
150 iterator
->insert_before(iterator
, attr
);
155 iterator
->destroy(iterator
);
158 list
->insert_last(list
, attr
);
163 * Described in header.
165 bool ietfAttr_list_equals(linked_list_t
*list_a
, linked_list_t
*list_b
)
169 /* lists must have the same number of attributes */
170 if (list_a
->get_count(list_a
) != list_b
->get_count(list_b
))
174 /* empty lists - no attributes */
175 if (list_a
->get_count(list_a
) == 0)
180 /* compare two alphabetically-sorted lists */
182 iterator_t
*iterator_a
= list_a
->create_iterator(list_a
, TRUE
);
183 iterator_t
*iterator_b
= list_b
->create_iterator(list_b
, TRUE
);
184 ietfAttr_t
*attr_a
, *attr_b
;
186 while (iterator_a
->iterate(iterator_a
, (void **)&attr_a
) &&
187 iterator_b
->iterate(iterator_b
, (void **)&attr_b
))
189 if (attr_a
->compare(attr_a
, attr_b
) != 0)
191 /* we have a mismatch */
196 iterator_a
->destroy(iterator_a
);
197 iterator_b
->destroy(iterator_b
);
203 * Described in header.
205 void ietfAttr_list_list(linked_list_t
*list
, FILE *out
)
207 iterator_t
*iterator
= list
->create_iterator(list
, TRUE
);
211 while (iterator
->iterate(iterator
, (void **)&attr
))
224 case IETF_ATTRIBUTE_OCTETS
:
225 case IETF_ATTRIBUTE_STRING
:
226 fprintf(out
, "%.*s", (int)attr
->value
.len
, attr
->value
.ptr
);
228 case IETF_ATTRIBUTE_OID
:
230 int oid
= known_oid(attr
->value
);
232 if (oid
== OID_UNKNOWN
)
234 fprintf(out
, "0x#B", &attr
->value
);
238 fprintf(out
, "%s", oid_names
[oid
]);
246 iterator
->destroy(iterator
);
250 * Described in header.
252 void ietfAttr_list_create_from_string(char *msg
, linked_list_t
*list
)
254 chunk_t line
= { msg
, strlen(msg
) };
256 while (eat_whitespace(&line
))
260 /* extract the next comma-separated group attribute */
261 if (!extract_token(&group
, ',', &line
))
267 /* remove any trailing spaces */
268 while (group
.len
> 0 && *(group
.ptr
+ group
.len
- 1) == ' ')
273 /* add the group attribute to the list */
276 ietfAttr_t
*attr
= ietfAttr_create(IETF_ATTRIBUTE_STRING
, group
);
278 ietfAttr_add(list
, attr
);
284 * ASN.1 definition of ietfAttrSyntax
286 static const asn1Object_t ietfAttrSyntaxObjects
[] =
288 { 0, "ietfAttrSyntax", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
289 { 1, "policyAuthority", ASN1_CONTEXT_C_0
, ASN1_OPT
|
291 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 2 */
292 { 1, "values", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 3 */
293 { 2, "octets", ASN1_OCTET_STRING
, ASN1_OPT
|
295 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 5 */
296 { 2, "oid", ASN1_OID
, ASN1_OPT
|
298 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 7 */
299 { 2, "string", ASN1_UTF8STRING
, ASN1_OPT
|
301 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 9 */
302 { 1, "end loop", ASN1_EOC
, ASN1_END
} /* 10 */
305 #define IETF_ATTR_OCTETS 4
306 #define IETF_ATTR_OID 6
307 #define IETF_ATTR_STRING 8
308 #define IETF_ATTR_ROOF 11
311 * Described in header.
313 void ietfAttr_list_create_from_chunk(chunk_t chunk
, linked_list_t
*list
, int level0
)
320 asn1_init(&ctx
, chunk
, level0
, FALSE
, FALSE
);
322 while (objectID
< IETF_ATTR_ROOF
)
324 if (!extract_object(ietfAttrSyntaxObjects
, &objectID
, &object
, &level
, &ctx
))
331 case IETF_ATTR_OCTETS
:
333 case IETF_ATTR_STRING
:
335 ietfAttribute_t kind
= (objectID
- IETF_ATTR_OCTETS
) / 2;
336 ietfAttr_t
*attr
= ietfAttr_create(kind
, object
);
337 ietfAttr_add(list
, attr
);
348 * Described in header.
350 chunk_t
ietfAttr_list_encode(linked_list_t
*list
)
352 chunk_t ietfAttributes
;
355 iterator_t
*iterator
= list
->create_iterator(list
, TRUE
);
359 /* precalculate the total size of all values */
360 while (iterator
->iterate(iterator
, (void **)&attr
))
362 size_t len
= attr
->value
.len
;
364 size
+= 1 + (len
> 0) + (len
>= 128) + (len
>= 256) + (len
>= 65536) + len
;
366 iterator
->destroy(iterator
);
368 pos
= build_asn1_object(&ietfAttributes
, ASN1_SEQUENCE
, size
);
370 iterator
= list
->create_iterator(list
, TRUE
);
371 while (iterator
->iterate(iterator
, (void **)&attr
))
373 chunk_t ietfAttribute
;
374 asn1_t type
= ASN1_NULL
;
378 case IETF_ATTRIBUTE_OCTETS
:
379 type
= ASN1_OCTET_STRING
;
381 case IETF_ATTRIBUTE_STRING
:
382 type
= ASN1_UTF8STRING
;
384 case IETF_ATTRIBUTE_OID
:
388 ietfAttribute
= asn1_simple_object(type
, attr
->value
);
390 /* copy ietfAttribute into ietfAttributes chunk */
391 memcpy(pos
, ietfAttribute
.ptr
, ietfAttribute
.len
);
392 pos
+= ietfAttribute
.len
;
393 free(ietfAttribute
.ptr
);
395 iterator
->destroy(iterator
);
397 return asn1_wrap(ASN1_SEQUENCE
, "m", ietfAttributes
);
401 * Described in header.
403 void ietfAttr_list_destroy(linked_list_t
*list
)
405 list
->destroy_offset(list
, offsetof(ietfAttr_t
, destroy
));