99d79921387cfd6afcd31f98aa6868417cff51e1
[strongswan.git] / src / libcharon / plugins / tnccs_20 / messages / pb_error_message.c
1 /*
2 * Copyright (C) 2010 Sansar Choinyambuu
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 "pb_error_message.h"
17 #include "../tnccs_20_types.h"
18
19 #include <tls_writer.h>
20 #include <tls_reader.h>
21 #include <debug.h>
22
23 typedef struct private_pb_error_message_t private_pb_error_message_t;
24
25 /**
26 * PB-Error message (see section 4.9 of RFC 5793)
27 *
28 * 0 1 2 3
29 * 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
30 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31 * | Flags | Error Code Vendor ID |
32 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33 * | Error Code | Reserved |
34 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35 * | Error Parameters (Variable Length) |
36 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 */
38
39 #define ERROR_FLAG_NONE 0x00
40 #define ERROR_FLAG_FATAL (1<<7)
41 #define ERROR_RESERVED 0x0000
42 #define ERROR_HEADER_SIZE 8
43
44 /**
45 * Private data of a pb_error_message_t object.
46 *
47 */
48 struct private_pb_error_message_t {
49 /**
50 * Public pb_error_message_t interface.
51 */
52 pb_error_message_t public;
53
54 /**
55 * PB-TNC message type
56 */
57 pb_tnc_msg_type_t type;
58
59 /**
60 * Fatal flag
61 */
62 bool fatal;
63
64 /**
65 * PB Error Code Vendor ID
66 */
67 u_int32_t vendor_id;
68
69 /**
70 * PB Error Code
71 */
72 u_int16_t error_code;
73
74 /**
75 * PB Error Parameters
76 */
77 u_int32_t error_parameters;
78
79 /**
80 * Encoded message
81 */
82 chunk_t encoding;
83 };
84
85 METHOD(pb_tnc_message_t, get_type, pb_tnc_msg_type_t,
86 private_pb_error_message_t *this)
87 {
88 return this->type;
89 }
90
91 METHOD(pb_tnc_message_t, get_encoding, chunk_t,
92 private_pb_error_message_t *this)
93 {
94 return this->encoding;
95 }
96
97 METHOD(pb_tnc_message_t, build, void,
98 private_pb_error_message_t *this)
99 {
100 tls_writer_t *writer;
101
102 /* build message header */
103 writer = tls_writer_create(ERROR_HEADER_SIZE);
104 writer->write_uint8 (writer, this->fatal ?
105 ERROR_FLAG_FATAL : ERROR_FLAG_NONE);
106 writer->write_uint24(writer, this->vendor_id);
107 writer->write_uint16(writer, this->error_code);
108 writer->write_uint16(writer, ERROR_RESERVED);
109
110 /* create encoding by concatenating message header and message body */
111 free(this->encoding.ptr);
112
113 if (this->error_parameters)
114 {
115 if (this->error_code == PB_ERROR_VERSION_NOT_SUPPORTED)
116 {
117 /* Bad version */
118 writer->write_uint8(writer, this->error_parameters);
119 writer->write_uint8(writer, 2); /* Max version */
120 writer->write_uint8(writer, 2); /* Min version */
121 writer->write_uint8(writer, 0); /* Reserved */
122 }
123 else
124 {
125 /* Error parameters */
126 writer->write_uint32(writer, this->error_parameters);
127 }
128 }
129 this->encoding = writer->get_buf(writer);
130 this->encoding = chunk_clone(this->encoding);
131 writer->destroy(writer);
132 }
133
134 METHOD(pb_tnc_message_t, process, status_t,
135 private_pb_error_message_t *this)
136 {
137 u_int8_t flags;
138 u_int16_t reserved;
139 size_t error_parameters_len;
140 tls_reader_t *reader;
141
142 if (this->encoding.len < ERROR_HEADER_SIZE)
143 {
144 DBG1(DBG_TNC,"%N message is shorter than header size of %u bytes",
145 pb_tnc_msg_type_names, PB_MSG_ERROR, ERROR_HEADER_SIZE);
146 return FAILED;
147 }
148
149 /* process message header */
150 reader = tls_reader_create(this->encoding);
151 reader->read_uint8 (reader, &flags);
152 reader->read_uint24(reader, &this->vendor_id);
153 reader->read_uint16(reader, &this->error_code);
154 reader->read_uint16(reader, &reserved);
155
156 /* process error parameters */
157 error_parameters_len = reader->remaining(reader);
158 if (error_parameters_len)
159 {
160 reader->read_uint32(reader, &this->error_parameters);
161 }
162 reader->destroy(reader);
163 return SUCCESS;
164 }
165
166 METHOD(pb_tnc_message_t, destroy, void,
167 private_pb_error_message_t *this)
168 {
169 free(this->encoding.ptr);
170 free(this);
171 }
172
173 METHOD(pb_error_message_t, get_vendor_id, u_int32_t,
174 private_pb_error_message_t *this)
175 {
176 return this->vendor_id;
177 }
178
179 METHOD(pb_error_message_t, get_error_code, u_int16_t,
180 private_pb_error_message_t *this)
181 {
182 return this->error_code;
183 }
184
185 METHOD(pb_error_message_t, get_parameters, u_int32_t,
186 private_pb_error_message_t *this)
187 {
188 return this->error_parameters;
189 }
190
191 METHOD(pb_error_message_t, get_fatal_flag, bool,
192 private_pb_error_message_t *this)
193 {
194 return this->fatal;
195 }
196
197 METHOD(pb_error_message_t, set_fatal_flag, void,
198 private_pb_error_message_t *this, bool fatal)
199 {
200 this->fatal = fatal;
201 }
202
203 /**
204 * See header
205 */
206 pb_tnc_message_t *pb_error_message_create_from_data(chunk_t data)
207 {
208 private_pb_error_message_t *this;
209
210 INIT(this,
211 .public = {
212 .pb_interface = {
213 .get_type = _get_type,
214 .get_encoding = _get_encoding,
215 .build = _build,
216 .process = _process,
217 .destroy = _destroy,
218 },
219 .get_vendor_id = _get_vendor_id,
220 .get_error_code = _get_error_code,
221 .get_parameters = _get_parameters,
222 .get_fatal_flag = _get_fatal_flag,
223 .set_fatal_flag = _set_fatal_flag,
224 },
225 .type = PB_MSG_ERROR,
226 .encoding = chunk_clone(data),
227 );
228
229 return &this->public.pb_interface;
230 }
231
232 /**
233 * See header
234 */
235 pb_tnc_message_t *pb_error_message_create(u_int32_t vendor_id,
236 pb_tnc_error_code_t error_code)
237 {
238 private_pb_error_message_t *this;
239
240 INIT(this,
241 .public = {
242 .pb_interface = {
243 .get_type = _get_type,
244 .get_encoding = _get_encoding,
245 .build = _build,
246 .process = _process,
247 .destroy = _destroy,
248 },
249 .get_vendor_id = _get_vendor_id,
250 .get_error_code = _get_error_code,
251 .get_parameters = _get_parameters,
252 .get_fatal_flag = _get_fatal_flag,
253 .set_fatal_flag = _set_fatal_flag,
254 },
255 .type = PB_MSG_ERROR,
256 .vendor_id = vendor_id,
257 .error_code = error_code,
258 );
259
260 return &this->public.pb_interface;
261 }
262
263 /**
264 * See header
265 */
266 pb_tnc_message_t *pb_error_message_create_with_parameter(u_int32_t vendor_id,
267 pb_tnc_error_code_t error_code,
268 u_int32_t error_parameters)
269 {
270 private_pb_error_message_t *this;
271
272 INIT(this,
273 .public = {
274 .pb_interface = {
275 .get_type = _get_type,
276 .get_encoding = _get_encoding,
277 .build = _build,
278 .process = _process,
279 .destroy = _destroy,
280 },
281 .get_vendor_id = _get_vendor_id,
282 .get_error_code = _get_error_code,
283 .get_parameters = _get_parameters,
284 .get_fatal_flag = _get_fatal_flag,
285 .set_fatal_flag = _set_fatal_flag,
286 },
287 .type = PB_MSG_ERROR,
288 .vendor_id = vendor_id,
289 .error_code = error_code,
290 .error_parameters = error_parameters,
291 );
292
293 return &this->public.pb_interface;
294 }