2 * Copyright (C) 2017 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
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>.
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
16 #include "ietf_swima_attr_req.h"
17 #include "swima/swima_record.h"
19 #include <pa_tnc/pa_tnc_msg.h>
20 #include <bio/bio_writer.h>
21 #include <bio/bio_reader.h>
22 #include <utils/debug.h>
23 #include <collections/linked_list.h>
25 typedef struct private_ietf_swima_attr_req_t private_ietf_swima_attr_req_t
;
29 * see section 5.7 of IETF SW Inventory Message and Attributes for PA-TNC
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 * |C|S|R| Reserved| Software Identifier Count |
35 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40 * | Software Identifier Length | Software Identifier (Var Len) |
41 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44 #define SW_REQ_RESERVED_MASK 0xE0
47 * Private data of an ietf_swima_attr_req_t object.
49 struct private_ietf_swima_attr_req_t
{
52 * Public members of ietf_swima_attr_req_t
54 ietf_swima_attr_req_t
public;
57 * Vendor-specific attribute type
62 * Length of attribute value
67 * Attribute value or segment
87 * Inventory of Target Software Identifiers
89 swima_inventory_t
*targets
;
97 METHOD(pa_tnc_attr_t
, get_type
, pen_type_t
,
98 private_ietf_swima_attr_req_t
*this)
103 METHOD(pa_tnc_attr_t
, get_value
, chunk_t
,
104 private_ietf_swima_attr_req_t
*this)
109 METHOD(pa_tnc_attr_t
, get_noskip_flag
, bool,
110 private_ietf_swima_attr_req_t
*this)
112 return this->noskip_flag
;
115 METHOD(pa_tnc_attr_t
, set_noskip_flag
,void,
116 private_ietf_swima_attr_req_t
*this, bool noskip
)
118 this->noskip_flag
= noskip
;
121 METHOD(pa_tnc_attr_t
, build
, void,
122 private_ietf_swima_attr_req_t
*this)
124 bio_writer_t
*writer
;
125 swima_record_t
*sw_record
;
126 uint32_t earliest_eid
;
128 enumerator_t
*enumerator
;
134 earliest_eid
= this->targets
->get_eid(this->targets
, NULL
);
136 writer
= bio_writer_create(IETF_SWIMA_REQ_MIN_SIZE
);
137 writer
->write_uint8 (writer
, this->flags
);
138 writer
->write_uint24(writer
, this->targets
->get_count(this->targets
));
139 writer
->write_uint32(writer
, this->request_id
);
140 writer
->write_uint32(writer
, earliest_eid
);
142 enumerator
= this->targets
->create_enumerator(this->targets
);
143 while (enumerator
->enumerate(enumerator
, &sw_record
))
145 sw_id
= sw_record
->get_sw_id(sw_record
, NULL
);
146 writer
->write_data16(writer
, sw_id
);
148 enumerator
->destroy(enumerator
);
150 this->value
= writer
->extract_buf(writer
);
151 this->length
= this->value
.len
;
152 writer
->destroy(writer
);
155 METHOD(pa_tnc_attr_t
, process
, status_t
,
156 private_ietf_swima_attr_req_t
*this, uint32_t *offset
)
158 bio_reader_t
*reader
;
159 swima_record_t
*sw_record
;
160 uint32_t sw_id_count
, earliest_eid
;
165 if (this->value
.len
< this->length
)
169 if (this->value
.len
< IETF_SWIMA_REQ_MIN_SIZE
)
171 DBG1(DBG_TNC
, "insufficient data for SW Request");
175 reader
= bio_reader_create(this->value
);
176 reader
->read_uint8 (reader
, &this->flags
);
177 reader
->read_uint24(reader
, &sw_id_count
);
178 reader
->read_uint32(reader
, &this->request_id
);
179 reader
->read_uint32(reader
, &earliest_eid
);
181 *offset
= IETF_SWIMA_REQ_MIN_SIZE
;
182 this->flags
&= SW_REQ_RESERVED_MASK
;
183 this->targets
->set_eid(this->targets
, earliest_eid
, 0);
185 while (sw_id_count
--)
187 if (!reader
->read_data16(reader
, &sw_id
))
189 DBG1(DBG_TNC
, "insufficient data for Software ID");
190 reader
->destroy(reader
);
193 *offset
+= 2 + sw_id
.len
;
195 sw_record
= swima_record_create(0, sw_id
, chunk_empty
);
196 this->targets
->add(this->targets
, sw_record
);
198 reader
->destroy(reader
);
203 METHOD(pa_tnc_attr_t
, add_segment
, void,
204 private_ietf_swima_attr_req_t
*this, chunk_t segment
)
206 this->value
= chunk_cat("mc", this->value
, segment
);
209 METHOD(pa_tnc_attr_t
, get_ref
, pa_tnc_attr_t
*,
210 private_ietf_swima_attr_req_t
*this)
213 return &this->public.pa_tnc_attribute
;
216 METHOD(pa_tnc_attr_t
, destroy
, void,
217 private_ietf_swima_attr_req_t
*this)
219 if (ref_put(&this->ref
))
221 this->targets
->destroy(this->targets
);
222 free(this->value
.ptr
);
227 METHOD(ietf_swima_attr_req_t
, get_flags
, uint8_t,
228 private_ietf_swima_attr_req_t
*this)
233 METHOD(ietf_swima_attr_req_t
, get_request_id
, uint32_t,
234 private_ietf_swima_attr_req_t
*this)
236 return this->request_id
;
239 METHOD(ietf_swima_attr_req_t
, set_targets
, void,
240 private_ietf_swima_attr_req_t
*this, swima_inventory_t
*targets
)
242 this->targets
->destroy(this->targets
);
243 this->targets
= targets
->get_ref(targets
);
246 METHOD(ietf_swima_attr_req_t
, get_targets
, swima_inventory_t
*,
247 private_ietf_swima_attr_req_t
*this)
249 return this->targets
;
253 * Described in header.
255 pa_tnc_attr_t
*ietf_swima_attr_req_create(uint8_t flags
, uint32_t request_id
)
257 private_ietf_swima_attr_req_t
*this;
261 .pa_tnc_attribute
= {
262 .get_type
= _get_type
,
263 .get_value
= _get_value
,
264 .get_noskip_flag
= _get_noskip_flag
,
265 .set_noskip_flag
= _set_noskip_flag
,
268 .add_segment
= _add_segment
,
272 .get_flags
= _get_flags
,
273 .get_request_id
= _get_request_id
,
274 .set_targets
= _set_targets
,
275 .get_targets
= _get_targets
,
277 .type
= { PEN_IETF
, IETF_ATTR_SW_REQUEST
},
278 .flags
= flags
& SW_REQ_RESERVED_MASK
,
279 .request_id
= request_id
,
280 .targets
= swima_inventory_create(),
284 return &this->public.pa_tnc_attribute
;
288 * Described in header.
290 pa_tnc_attr_t
*ietf_swima_attr_req_create_from_data(size_t length
, chunk_t data
)
292 private_ietf_swima_attr_req_t
*this;
296 .pa_tnc_attribute
= {
297 .get_type
= _get_type
,
298 .get_value
= _get_value
,
299 .get_noskip_flag
= _get_noskip_flag
,
300 .set_noskip_flag
= _set_noskip_flag
,
303 .add_segment
= _add_segment
,
307 .get_flags
= _get_flags
,
308 .get_request_id
= _get_request_id
,
309 .set_targets
= _set_targets
,
310 .get_targets
= _get_targets
,
312 .type
= { PEN_IETF
, IETF_ATTR_SW_REQUEST
},
314 .value
= chunk_clone(data
),
315 .targets
= swima_inventory_create(),
319 return &this->public.pa_tnc_attribute
;