2 * Copyright (C) 2010 Sansar Choinyambuu
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 "pb_error_msg.h"
18 #include <tnc/tnccs/tnccs.h>
20 #include <bio/bio_writer.h>
21 #include <bio/bio_reader.h>
23 #include <utils/debug.h>
25 ENUM(pb_tnc_error_code_names
, PB_ERROR_UNEXPECTED_BATCH_TYPE
,
26 PB_ERROR_VERSION_NOT_SUPPORTED
,
27 "Unexpected Batch Type",
30 "Unsupported Mandatory Message",
31 "Version Not Supported"
34 typedef struct private_pb_error_msg_t private_pb_error_msg_t
;
37 * PB-Error message (see section 4.9 of RFC 5793)
40 * 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
41 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42 * | Flags | Error Code Vendor ID |
43 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44 * | Error Code | Reserved |
45 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46 * | Error Parameters (Variable Length) |
47 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 #define ERROR_FLAG_NONE 0x00
51 #define ERROR_FLAG_FATAL (1<<7)
52 #define ERROR_RESERVED 0x0000
53 #define ERROR_HEADER_SIZE 8
56 * Private data of a pb_error_msg_t object.
59 struct private_pb_error_msg_t
{
61 * Public pb_error_msg_t interface.
63 pb_error_msg_t
public;
68 pb_tnc_msg_type_t type
;
76 * PB Error Code Vendor ID
88 u_int32_t error_offset
;
91 * Bad PB-TNC version received
106 METHOD(pb_tnc_msg_t
, get_type
, pb_tnc_msg_type_t
,
107 private_pb_error_msg_t
*this)
112 METHOD(pb_tnc_msg_t
, get_encoding
, chunk_t
,
113 private_pb_error_msg_t
*this)
115 return this->encoding
;
118 METHOD(pb_tnc_msg_t
, build
, void,
119 private_pb_error_msg_t
*this)
121 bio_writer_t
*writer
;
123 if (this->encoding
.ptr
)
128 /* build message header */
129 writer
= bio_writer_create(ERROR_HEADER_SIZE
);
130 writer
->write_uint8 (writer
, this->fatal
?
131 ERROR_FLAG_FATAL
: ERROR_FLAG_NONE
);
132 writer
->write_uint24(writer
, this->vendor_id
);
133 writer
->write_uint16(writer
, this->error_code
);
134 writer
->write_uint16(writer
, ERROR_RESERVED
);
136 /* build message body */
137 if (this->error_code
== PB_ERROR_VERSION_NOT_SUPPORTED
)
140 writer
->write_uint8(writer
, this->bad_version
);
141 writer
->write_uint8(writer
, PB_TNC_VERSION
); /* Max version */
142 writer
->write_uint8(writer
, PB_TNC_VERSION
); /* Min version */
143 writer
->write_uint8(writer
, 0x00); /* Reserved */
148 writer
->write_uint32(writer
, this->error_offset
);
150 this->encoding
= writer
->get_buf(writer
);
151 this->encoding
= chunk_clone(this->encoding
);
152 writer
->destroy(writer
);
155 METHOD(pb_tnc_msg_t
, process
, status_t
,
156 private_pb_error_msg_t
*this, u_int32_t
*offset
)
158 u_int8_t flags
, max_version
, min_version
;
160 bio_reader_t
*reader
;
162 if (this->encoding
.len
< ERROR_HEADER_SIZE
)
164 DBG1(DBG_TNC
,"%N message is shorter than header size of %u bytes",
165 pb_tnc_msg_type_names
, PB_MSG_ERROR
, ERROR_HEADER_SIZE
);
170 /* process message header */
171 reader
= bio_reader_create(this->encoding
);
172 reader
->read_uint8 (reader
, &flags
);
173 reader
->read_uint24(reader
, &this->vendor_id
);
174 reader
->read_uint16(reader
, &this->error_code
);
175 reader
->read_uint16(reader
, &reserved
);
176 this->fatal
= (flags
& ERROR_FLAG_FATAL
) != ERROR_FLAG_NONE
;
178 if (this->vendor_id
== PEN_IETF
&& reader
->remaining(reader
) == 4)
180 if (this->error_code
== PB_ERROR_VERSION_NOT_SUPPORTED
)
182 reader
->read_uint8(reader
, &this->bad_version
);
183 reader
->read_uint8(reader
, &max_version
);
184 reader
->read_uint8(reader
, &min_version
);
188 reader
->read_uint32(reader
, &this->error_offset
);
191 reader
->destroy(reader
);
196 METHOD(pb_tnc_msg_t
, get_ref
, pb_tnc_msg_t
*,
197 private_pb_error_msg_t
*this)
200 return &this->public.pb_interface
;
203 METHOD(pb_tnc_msg_t
, destroy
, void,
204 private_pb_error_msg_t
*this)
206 if (ref_put(&this->ref
))
208 free(this->encoding
.ptr
);
213 METHOD(pb_error_msg_t
, get_fatal_flag
, bool,
214 private_pb_error_msg_t
*this)
219 METHOD(pb_error_msg_t
, get_vendor_id
, u_int32_t
,
220 private_pb_error_msg_t
*this)
222 return this->vendor_id
;
225 METHOD(pb_error_msg_t
, get_error_code
, u_int16_t
,
226 private_pb_error_msg_t
*this)
228 return this->error_code
;
231 METHOD(pb_error_msg_t
, get_offset
, u_int32_t
,
232 private_pb_error_msg_t
*this)
234 return this->error_offset
;
237 METHOD(pb_error_msg_t
, get_bad_version
, u_int8_t
,
238 private_pb_error_msg_t
*this)
240 return this->bad_version
;
243 METHOD(pb_error_msg_t
, set_bad_version
, void,
244 private_pb_error_msg_t
*this, u_int8_t version
)
246 this->bad_version
= version
;
252 pb_tnc_msg_t
* pb_error_msg_create(bool fatal
, u_int32_t vendor_id
,
253 pb_tnc_error_code_t error_code
)
255 private_pb_error_msg_t
*this;
260 .get_type
= _get_type
,
261 .get_encoding
= _get_encoding
,
267 .get_fatal_flag
= _get_fatal_flag
,
268 .get_vendor_id
= _get_vendor_id
,
269 .get_error_code
= _get_error_code
,
270 .get_offset
= _get_offset
,
271 .get_bad_version
= _get_bad_version
,
272 .set_bad_version
= _set_bad_version
,
274 .type
= PB_MSG_ERROR
,
277 .vendor_id
= vendor_id
,
278 .error_code
= error_code
,
281 return &this->public.pb_interface
;
287 pb_tnc_msg_t
* pb_error_msg_create_with_offset(bool fatal
, u_int32_t vendor_id
,
288 pb_tnc_error_code_t error_code
,
289 u_int32_t error_offset
)
291 private_pb_error_msg_t
*this;
296 .get_type
= _get_type
,
297 .get_encoding
= _get_encoding
,
303 .get_fatal_flag
= _get_fatal_flag
,
304 .get_vendor_id
= _get_vendor_id
,
305 .get_error_code
= _get_error_code
,
306 .get_offset
= _get_offset
,
307 .get_bad_version
= _get_bad_version
,
308 .set_bad_version
= _set_bad_version
,
310 .type
= PB_MSG_ERROR
,
313 .vendor_id
= vendor_id
,
314 .error_code
= error_code
,
315 .error_offset
= error_offset
,
318 return &this->public.pb_interface
;
324 pb_tnc_msg_t
*pb_error_msg_create_from_data(chunk_t data
)
326 private_pb_error_msg_t
*this;
331 .get_type
= _get_type
,
332 .get_encoding
= _get_encoding
,
338 .get_fatal_flag
= _get_fatal_flag
,
339 .get_vendor_id
= _get_vendor_id
,
340 .get_error_code
= _get_error_code
,
341 .get_offset
= _get_offset
,
342 .get_bad_version
= _get_bad_version
,
343 .set_bad_version
= _set_bad_version
,
345 .type
= PB_MSG_ERROR
,
347 .encoding
= chunk_clone(data
),
350 return &this->public.pb_interface
;