use pen_type_t for attribute request entries
[strongswan.git] / src / libimcv / ietf / ietf_attr_attr_request.c
1 /*
2 * Copyright (C) 2012 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "imcv.h"
17 #include "ietf_attr_attr_request.h"
18
19 #include <pa_tnc/pa_tnc_msg.h>
20 #include <bio/bio_writer.h>
21 #include <bio/bio_reader.h>
22 #include <utils/linked_list.h>
23
24 #include <debug.h>
25
26 typedef struct private_ietf_attr_attr_request_t private_ietf_attr_attr_request_t;
27
28 /**
29 * PA-TNC Attribute Request type (see section 4.2.1 of RFC 5792)
30 *
31 * 1 2 3
32 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
33 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34 * | Reserved | PA-TNC Attribute Vendor ID |
35 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36 * | PA-TNC Attribute Type |
37 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
38 * | Reserved | PA-TNC Attribute Vendor ID |
39 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40 * | PA-TNC Attribute Type |
41 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42 */
43
44 #define ATTR_REQUEST_ENTRY_SIZE 8
45
46 /**
47 * Private data of an ietf_attr_attr_request_t object.
48 */
49 struct private_ietf_attr_attr_request_t {
50
51 /**
52 * Public members of ietf_attr_attr_request_t
53 */
54 ietf_attr_attr_request_t public;
55
56 /**
57 * Vendor-specific attribute type
58 */
59 pen_type_t type;
60
61 /**
62 * Attribute value
63 */
64 chunk_t value;
65
66 /**
67 * Noskip flag
68 */
69 bool noskip_flag;
70
71 /**
72 * List of requested attribute types
73 */
74 linked_list_t *list;
75
76 /**
77 * Reference count
78 */
79 refcount_t ref;
80 };
81
82 METHOD(pa_tnc_attr_t, get_type, pen_type_t,
83 private_ietf_attr_attr_request_t *this)
84 {
85 return this->type;
86 }
87
88 METHOD(pa_tnc_attr_t, get_value, chunk_t,
89 private_ietf_attr_attr_request_t *this)
90 {
91 return this->value;
92 }
93
94 METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
95 private_ietf_attr_attr_request_t *this)
96 {
97 return this->noskip_flag;
98 }
99
100 METHOD(pa_tnc_attr_t, set_noskip_flag,void,
101 private_ietf_attr_attr_request_t *this, bool noskip)
102 {
103 this->noskip_flag = noskip;
104 }
105
106 METHOD(pa_tnc_attr_t, build, void,
107 private_ietf_attr_attr_request_t *this)
108 {
109 bio_writer_t *writer;
110 enumerator_t *enumerator;
111 pen_type_t *entry;
112
113 if (this->value.ptr)
114 {
115 return;
116 }
117 writer = bio_writer_create(ATTR_REQUEST_ENTRY_SIZE *
118 this->list->get_count(this->list));
119
120 enumerator = this->list->create_enumerator(this->list);
121 while (enumerator->enumerate(enumerator, &entry))
122 {
123 writer->write_uint32(writer, entry->vendor_id);
124 writer->write_uint32(writer, entry->type);
125 }
126 enumerator->destroy(enumerator);
127
128 this->value = chunk_clone(writer->get_buf(writer));
129 writer->destroy(writer);
130 }
131
132 METHOD(ietf_attr_attr_request_t, add, void,
133 private_ietf_attr_attr_request_t *this, pen_t vendor_id, u_int32_t type)
134 {
135 pen_type_t *entry;
136
137 entry = malloc_thing(pen_type_t);
138 entry->vendor_id = vendor_id;
139 entry->type = type;
140 this->list->insert_last(this->list, entry);
141 }
142
143 METHOD(pa_tnc_attr_t, process, status_t,
144 private_ietf_attr_attr_request_t *this, u_int32_t *offset)
145 {
146 bio_reader_t *reader;
147 enum_name_t *pa_attr_names;
148 pen_t vendor_id;
149 u_int32_t type;
150 u_int8_t reserved;
151 int count;
152
153 count = this->value.len / ATTR_REQUEST_ENTRY_SIZE;
154 if (this->value.len != ATTR_REQUEST_ENTRY_SIZE * count)
155 {
156 DBG1(DBG_TNC, "incorrect attribute length for IETF attribute request");
157 *offset = 0;
158 return FAILED;
159 }
160
161 reader = bio_reader_create(this->value);
162 while (count--)
163 {
164 reader->read_uint8 (reader, &reserved);
165 reader->read_uint24(reader, &vendor_id);
166 reader->read_uint32(reader, &type);
167
168 pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
169 vendor_id);
170 if (pa_attr_names)
171 {
172 DBG2(DBG_TNC, " 0x%06x/0x%08x '%N/%N'", vendor_id, type,
173 pen_names, vendor_id, pa_attr_names, type);
174 }
175 else
176 {
177 DBG2(DBG_TNC, " 0x%06x/0x%08x '%N'", vendor_id, type,
178 pen_names, vendor_id);
179 }
180 add(this, vendor_id, type);
181 }
182 reader->destroy(reader);
183
184 return SUCCESS;
185 }
186
187 METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
188 private_ietf_attr_attr_request_t *this)
189 {
190 ref_get(&this->ref);
191 return &this->public.pa_tnc_attribute;
192 }
193
194 METHOD(pa_tnc_attr_t, destroy, void,
195 private_ietf_attr_attr_request_t *this)
196 {
197 if (ref_put(&this->ref))
198 {
199 this->list->destroy_function(this->list, free);
200 free(this->value.ptr);
201 free(this);
202 }
203 }
204
205 METHOD(ietf_attr_attr_request_t, create_enumerator, enumerator_t*,
206 private_ietf_attr_attr_request_t *this)
207 {
208 return this->list->create_enumerator(this->list);
209 }
210
211 /**
212 * Described in header.
213 */
214 pa_tnc_attr_t *ietf_attr_attr_request_create(pen_t vendor_id, u_int32_t type)
215 {
216 private_ietf_attr_attr_request_t *this;
217
218 INIT(this,
219 .public = {
220 .pa_tnc_attribute = {
221 .get_type = _get_type,
222 .get_value = _get_value,
223 .get_noskip_flag = _get_noskip_flag,
224 .set_noskip_flag = _set_noskip_flag,
225 .build = _build,
226 .process = _process,
227 .get_ref = _get_ref,
228 .destroy = _destroy,
229 },
230 .add = _add,
231 .create_enumerator = _create_enumerator,
232 },
233 .type = { PEN_IETF, IETF_ATTR_ATTRIBUTE_REQUEST },
234 .list = linked_list_create(),
235 .ref = 1,
236 );
237 add(this, vendor_id, type);
238
239 return &this->public.pa_tnc_attribute;
240 }
241
242 /**
243 * Described in header.
244 */
245 pa_tnc_attr_t *ietf_attr_attr_request_create_from_data(chunk_t data)
246 {
247 private_ietf_attr_attr_request_t *this;
248
249 INIT(this,
250 .public = {
251 .pa_tnc_attribute = {
252 .get_type = _get_type,
253 .get_value = _get_value,
254 .build = _build,
255 .process = _process,
256 .get_ref = _get_ref,
257 .destroy = _destroy,
258 },
259 .add = _add,
260 .create_enumerator = _create_enumerator,
261 },
262 .type = { PEN_IETF,IETF_ATTR_ATTRIBUTE_REQUEST },
263 .value = chunk_clone(data),
264 .list = linked_list_create(),
265 .ref = 1,
266 );
267
268 return &this->public.pa_tnc_attribute;
269 }
270