added TNC_TNCC_SendMessageLong() and TNC_TNCS_SendMessageLong() functions
[strongswan.git] / src / libcharon / plugins / tnccs_20 / messages / pb_pa_msg.c
1 /*
2 * Copyright (C) 2010 Sansar Choinyanbuu
3 * Copyright (C) 2010 Andreas Steffen
4 *
5 * HSR Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include "pb_pa_msg.h"
19
20 #include <tnc/tnccs/tnccs.h>
21
22 #include <bio/bio_writer.h>
23 #include <bio/bio_reader.h>
24 #include <pen/pen.h>
25 #include <debug.h>
26
27 typedef struct private_pb_pa_msg_t private_pb_pa_msg_t;
28
29 /**
30 * PB-PA message
31 *
32 * 0 1 2 3
33 * 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
34 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35 * | Flags | PA Message Vendor ID |
36 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 * | PA Subtype |
38 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 * | Posture Collector Identifier | Posture Validator Identifier |
40 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 * | PA Message Body (Variable Length) |
42 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 */
44
45 #define PA_FLAG_NONE 0x00
46 #define PA_FLAG_EXCL (1<<7)
47 #define PA_RESERVED_SUBTYPE 0xffffffff
48
49
50 /**
51 * Private data of a pb_pa_msg_t object.
52 *
53 */
54 struct private_pb_pa_msg_t {
55 /**
56 * Public pb_pa_msg_t interface.
57 */
58 pb_pa_msg_t public;
59
60 /**
61 * PB-TNC message type
62 */
63 pb_tnc_msg_type_t type;
64
65 /**
66 * Exclusive flag
67 */
68 bool excl;
69
70 /**
71 * PA Message Vendor ID
72 */
73 u_int32_t vendor_id;
74
75 /**
76 * PA Subtype
77 */
78 u_int32_t subtype;
79
80 /**
81 * Posture Validator Identifier
82 */
83 u_int16_t collector_id;
84
85 /**
86 * Posture Validator Identifier
87 */
88 u_int16_t validator_id;
89
90 /**
91 * PA Message Body
92 */
93 chunk_t msg_body;
94
95 /**
96 * Encoded message
97 */
98 chunk_t encoding;
99 };
100
101 METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
102 private_pb_pa_msg_t *this)
103 {
104 return this->type;
105 }
106
107 METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
108 private_pb_pa_msg_t *this)
109 {
110 return this->encoding;
111 }
112
113 METHOD(pb_tnc_msg_t, build, void,
114 private_pb_pa_msg_t *this)
115 {
116 chunk_t msg_header;
117 bio_writer_t *writer;
118
119 /* build message header */
120 writer = bio_writer_create(64);
121 writer->write_uint8 (writer, this->excl ? PA_FLAG_EXCL : PA_FLAG_NONE);
122 writer->write_uint24(writer, this->vendor_id);
123 writer->write_uint32(writer, this->subtype);
124 writer->write_uint16(writer, this->collector_id);
125 writer->write_uint16(writer, this->validator_id);
126 msg_header = writer->get_buf(writer);
127
128 /* create encoding by concatenating message header and message body */
129 free(this->encoding.ptr);
130 this->encoding = chunk_cat("cc", msg_header, this->msg_body);
131 writer->destroy(writer);
132 }
133
134 METHOD(pb_tnc_msg_t, process, status_t,
135 private_pb_pa_msg_t *this, u_int32_t *offset)
136 {
137 u_int8_t flags;
138 size_t msg_body_len;
139 bio_reader_t *reader;
140
141 /* process message header */
142 reader = bio_reader_create(this->encoding);
143 reader->read_uint8 (reader, &flags);
144 reader->read_uint24(reader, &this->vendor_id);
145 reader->read_uint32(reader, &this->subtype);
146 reader->read_uint16(reader, &this->collector_id);
147 reader->read_uint16(reader, &this->validator_id);
148 this->excl = ((flags & PA_FLAG_EXCL) != PA_FLAG_NONE);
149
150 /* process message body */
151 msg_body_len = reader->remaining(reader);
152 if (msg_body_len)
153 {
154 reader->read_data(reader, msg_body_len, &this->msg_body);
155 this->msg_body = chunk_clone(this->msg_body);
156 }
157 reader->destroy(reader);
158
159 if (this->vendor_id == PEN_RESERVED)
160 {
161 DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", PEN_RESERVED);
162 *offset = 1;
163 return FAILED;
164 }
165
166 if (this->subtype == PA_RESERVED_SUBTYPE)
167 {
168 DBG1(DBG_TNC, "PA Subtype 0x%08x is reserved", PA_RESERVED_SUBTYPE);
169 *offset = 4;
170 }
171
172 return SUCCESS;
173 }
174
175 METHOD(pb_tnc_msg_t, destroy, void,
176 private_pb_pa_msg_t *this)
177 {
178 free(this->encoding.ptr);
179 free(this->msg_body.ptr);
180 free(this);
181 }
182
183 METHOD(pb_pa_msg_t, get_vendor_id, u_int32_t,
184 private_pb_pa_msg_t *this, u_int32_t *subtype)
185 {
186 *subtype = this->subtype;
187 return this->vendor_id;
188 }
189
190 METHOD(pb_pa_msg_t, get_collector_id, u_int16_t,
191 private_pb_pa_msg_t *this)
192 {
193 return this->collector_id;
194 }
195
196 METHOD(pb_pa_msg_t, get_validator_id, u_int16_t,
197 private_pb_pa_msg_t *this)
198 {
199 return this->validator_id;
200 }
201
202 METHOD(pb_pa_msg_t, get_body, chunk_t,
203 private_pb_pa_msg_t *this)
204 {
205 return this->msg_body;
206 }
207
208 METHOD(pb_pa_msg_t, get_exclusive_flag, bool,
209 private_pb_pa_msg_t *this)
210 {
211 return this->excl;
212 }
213
214 /**
215 * See header
216 */
217 pb_tnc_msg_t *pb_pa_msg_create_from_data(chunk_t data)
218 {
219 private_pb_pa_msg_t *this;
220
221 INIT(this,
222 .public = {
223 .pb_interface = {
224 .get_type = _get_type,
225 .get_encoding = _get_encoding,
226 .process = _process,
227 .destroy = _destroy,
228 },
229 .get_vendor_id = _get_vendor_id,
230 .get_collector_id = _get_collector_id,
231 .get_validator_id = _get_validator_id,
232 .get_body = _get_body,
233 .get_exclusive_flag = _get_exclusive_flag,
234 },
235 .type = PB_MSG_PA,
236 .encoding = chunk_clone(data),
237 );
238
239 return &this->public.pb_interface;
240 }
241
242 /**
243 * See header
244 */
245 pb_tnc_msg_t *pb_pa_msg_create(u_int32_t vendor_id, u_int32_t subtype,
246 u_int16_t collector_id, u_int16_t validator_id,
247 bool excl, chunk_t msg_body)
248 {
249 private_pb_pa_msg_t *this;
250
251 INIT(this,
252 .public = {
253 .pb_interface = {
254 .get_type = _get_type,
255 .get_encoding = _get_encoding,
256 .build = _build,
257 .process = _process,
258 .destroy = _destroy,
259 },
260 .get_vendor_id = _get_vendor_id,
261 .get_collector_id = _get_collector_id,
262 .get_validator_id = _get_validator_id,
263 .get_body = _get_body,
264 .get_exclusive_flag = _get_exclusive_flag,
265 },
266 .type = PB_MSG_PA,
267 .vendor_id = vendor_id,
268 .subtype = subtype,
269 .collector_id = collector_id,
270 .validator_id = validator_id,
271 .excl = excl,
272 .msg_body = chunk_clone(msg_body),
273 );
274
275 return &this->public.pb_interface;
276 }