use pen_type_t for PA Message Subtype
[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 * Vendor-specific PA Subtype
72 */
73 pen_type_t subtype;
74
75 /**
76 * Posture Validator Identifier
77 */
78 u_int16_t collector_id;
79
80 /**
81 * Posture Validator Identifier
82 */
83 u_int16_t validator_id;
84
85 /**
86 * PA Message Body
87 */
88 chunk_t msg_body;
89
90 /**
91 * Encoded message
92 */
93 chunk_t encoding;
94 };
95
96 METHOD(pb_tnc_msg_t, get_type, pb_tnc_msg_type_t,
97 private_pb_pa_msg_t *this)
98 {
99 return this->type;
100 }
101
102 METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
103 private_pb_pa_msg_t *this)
104 {
105 return this->encoding;
106 }
107
108 METHOD(pb_tnc_msg_t, build, void,
109 private_pb_pa_msg_t *this)
110 {
111 chunk_t msg_header;
112 bio_writer_t *writer;
113
114 if (this->encoding.ptr)
115 {
116 return;
117 }
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->subtype.vendor_id);
123 writer->write_uint32(writer, this->subtype.type);
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 this->encoding = chunk_cat("cc", msg_header, this->msg_body);
130 writer->destroy(writer);
131 }
132
133 METHOD(pb_tnc_msg_t, process, status_t,
134 private_pb_pa_msg_t *this, u_int32_t *offset)
135 {
136 u_int8_t flags;
137 size_t msg_body_len;
138 bio_reader_t *reader;
139
140 /* process message header */
141 reader = bio_reader_create(this->encoding);
142 reader->read_uint8 (reader, &flags);
143 reader->read_uint24(reader, &this->subtype.vendor_id);
144 reader->read_uint32(reader, &this->subtype.type);
145 reader->read_uint16(reader, &this->collector_id);
146 reader->read_uint16(reader, &this->validator_id);
147 this->excl = ((flags & PA_FLAG_EXCL) != PA_FLAG_NONE);
148
149 /* process message body */
150 msg_body_len = reader->remaining(reader);
151 if (msg_body_len)
152 {
153 reader->read_data(reader, msg_body_len, &this->msg_body);
154 this->msg_body = chunk_clone(this->msg_body);
155 }
156 reader->destroy(reader);
157
158 if (this->subtype.vendor_id == PEN_RESERVED)
159 {
160 DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", PEN_RESERVED);
161 *offset = 1;
162 return FAILED;
163 }
164
165 if (this->subtype.type == PA_RESERVED_SUBTYPE)
166 {
167 DBG1(DBG_TNC, "PA Subtype 0x%08x is reserved", PA_RESERVED_SUBTYPE);
168 *offset = 4;
169 }
170
171 return SUCCESS;
172 }
173
174 METHOD(pb_tnc_msg_t, destroy, void,
175 private_pb_pa_msg_t *this)
176 {
177 free(this->encoding.ptr);
178 free(this->msg_body.ptr);
179 free(this);
180 }
181
182 METHOD(pb_pa_msg_t, get_subtype, pen_type_t,
183 private_pb_pa_msg_t *this)
184 {
185 return this->subtype;
186 }
187
188 METHOD(pb_pa_msg_t, get_collector_id, u_int16_t,
189 private_pb_pa_msg_t *this)
190 {
191 return this->collector_id;
192 }
193
194 METHOD(pb_pa_msg_t, get_validator_id, u_int16_t,
195 private_pb_pa_msg_t *this)
196 {
197 return this->validator_id;
198 }
199
200 METHOD(pb_pa_msg_t, get_body, chunk_t,
201 private_pb_pa_msg_t *this)
202 {
203 return this->msg_body;
204 }
205
206 METHOD(pb_pa_msg_t, get_exclusive_flag, bool,
207 private_pb_pa_msg_t *this)
208 {
209 return this->excl;
210 }
211
212 /**
213 * See header
214 */
215 pb_tnc_msg_t *pb_pa_msg_create_from_data(chunk_t data)
216 {
217 private_pb_pa_msg_t *this;
218
219 INIT(this,
220 .public = {
221 .pb_interface = {
222 .get_type = _get_type,
223 .get_encoding = _get_encoding,
224 .process = _process,
225 .destroy = _destroy,
226 },
227 .get_subtype = _get_subtype,
228 .get_collector_id = _get_collector_id,
229 .get_validator_id = _get_validator_id,
230 .get_body = _get_body,
231 .get_exclusive_flag = _get_exclusive_flag,
232 },
233 .type = PB_MSG_PA,
234 .encoding = chunk_clone(data),
235 );
236
237 return &this->public.pb_interface;
238 }
239
240 /**
241 * See header
242 */
243 pb_tnc_msg_t *pb_pa_msg_create(u_int32_t vendor_id, u_int32_t subtype,
244 u_int16_t collector_id, u_int16_t validator_id,
245 bool excl, chunk_t msg_body)
246 {
247 private_pb_pa_msg_t *this;
248
249 INIT(this,
250 .public = {
251 .pb_interface = {
252 .get_type = _get_type,
253 .get_encoding = _get_encoding,
254 .build = _build,
255 .process = _process,
256 .destroy = _destroy,
257 },
258 .get_subtype= _get_subtype,
259 .get_collector_id = _get_collector_id,
260 .get_validator_id = _get_validator_id,
261 .get_body = _get_body,
262 .get_exclusive_flag = _get_exclusive_flag,
263 },
264 .type = PB_MSG_PA,
265 .subtype = { vendor_id, subtype },
266 .collector_id = collector_id,
267 .validator_id = validator_id,
268 .excl = excl,
269 .msg_body = chunk_clone(msg_body),
270 );
271
272 return &this->public.pb_interface;
273 }