Implemented TCG/PB-PDP_Referral message
[strongswan.git] / src / libtnccs / plugins / tnccs_20 / messages / tcg / pb_pdp_referral_msg.c
1 /*
2 * Copyright (C) 2013 Andreas Steffen
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_pdp_referral_msg.h"
17
18 #include <bio/bio_writer.h>
19 #include <bio/bio_reader.h>
20 #include <utils/debug.h>
21
22 ENUM(pb_tnc_pdp_identifier_type_names, PB_PDP_ID_FQDN, PB_PDP_ID_IPV6,
23 "PDP FQDN ID",
24 "PDP IPv4 ID",
25 "PDP IPv6 ID"
26 );
27
28 typedef struct private_pb_pdp_referral_msg_t private_pb_pdp_referral_msg_t;
29
30 /**
31 * PB-PDP-Referral message (see section 3.1.1.1 of
32 * TCG TNC PDP Discovery and Validation Specification 1.0
33 *
34 * 0 1 2 3
35 * 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
36 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 * | Reserved | PDP Identifier Vendor ID |
38 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 * | PDP Identifier Type |
40 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 * | PDP Identifier (Variable Length) |
42 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 *
44 * Section 3.1.1.2.1 FQDN Identifier
45 *
46 * 0 1 2 3
47 * 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
48 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 * | Reserved | Protocol | Port Number |
50 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51 * | FQDN (Variable Length) |
52 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53 *
54 * Section 3.1.1.2.2 IPv4 Identifier
55 *
56 * 0 1 2 3
57 * 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
58 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 * | Reserved | Protocol | Port Number |
60 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61 * | IPv4 Address |
62 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63 *
64 * Section 3.1.1.2.3 IPv6 Identifier
65 *
66 * 0 1 2 3
67 * 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
68 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69 * | Reserved | Protocol | Port Number |
70 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71 * | IPv6 Address (octets 1-4) |
72 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73 * | IPv6 Address (octets 5-8) |
74 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75 * | IPv6 Address (octets 9-12) |
76 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77 * | IPv6 Address (octets 13-16) |
78 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
79 *
80 */
81
82 # define PDP_REFERRAL_HEADER_SIZE 8
83 # define PDP_REFERRAL_ID_HEADER_SIZE 4
84 # define PDP_REFERRAL_RESERVED 0x00
85 # define PDP_REFERRAL_PROTOCOL 0x00
86
87 /**
88 * Private data of a pb_pdp_referral_msg_t object.
89 *
90 */
91 struct private_pb_pdp_referral_msg_t {
92 /**
93 * Public pb_pdp_referral_msg_t interface.
94 */
95 pb_pdp_referral_msg_t public;
96
97 /**
98 * PB-TNC message type
99 */
100 pen_type_t type;
101
102 /**
103 * PDP Identifier Type
104 */
105 pen_type_t identifier_type;
106
107 /**
108 * PDP Identifier Value
109 */
110 chunk_t identifier;
111
112 /**
113 * PDP FQDN Identifier
114 */
115 chunk_t fqdn;
116
117 /**
118 * PT protocol the PDP is using
119 */
120 u_int8_t protocol;
121
122 /**
123 * PT port the PDP is using
124 */
125 u_int16_t port;
126
127 /**
128 * Encoded message
129 */
130 chunk_t encoding;
131 };
132
133 METHOD(pb_tnc_msg_t, get_type, pen_type_t,
134 private_pb_pdp_referral_msg_t *this)
135 {
136 return this->type;
137 }
138
139 METHOD(pb_tnc_msg_t, get_encoding, chunk_t,
140 private_pb_pdp_referral_msg_t *this)
141 {
142 return this->encoding;
143 }
144
145 METHOD(pb_tnc_msg_t, build, void,
146 private_pb_pdp_referral_msg_t *this)
147 {
148 bio_writer_t *writer;
149
150 if (this->encoding.ptr)
151 {
152 return;
153 }
154 writer = bio_writer_create(PDP_REFERRAL_HEADER_SIZE + this->identifier.len);
155 writer->write_uint8 (writer, PDP_REFERRAL_RESERVED);
156 writer->write_uint24(writer, this->identifier_type.vendor_id);
157 writer->write_uint32(writer, this->identifier_type.type);
158 writer->write_data (writer, this->identifier);
159
160 this->encoding = writer->get_buf(writer);
161 this->encoding = chunk_clone(this->encoding);
162 writer->destroy(writer);
163 }
164
165 METHOD(pb_tnc_msg_t, process, status_t,
166 private_pb_pdp_referral_msg_t *this, u_int32_t *offset)
167 {
168 bio_reader_t *reader;
169 u_int8_t reserved;
170
171 *offset = 0;
172
173 /* process message */
174 reader = bio_reader_create(this->encoding);
175 reader->read_uint8 (reader, &reserved);
176 reader->read_uint24(reader, &this->identifier_type.vendor_id);
177 reader->read_uint32(reader, &this->identifier_type.type);
178 reader->read_data (reader, reader->remaining(reader), &this->identifier);
179
180 this->identifier = chunk_clone(this->identifier);
181 reader->destroy(reader);
182
183 if (this->identifier_type.vendor_id == PEN_TCG &&
184 this->identifier_type.type == PB_PDP_ID_FQDN)
185 {
186 reader = bio_reader_create(this->identifier);
187 *offset += PDP_REFERRAL_HEADER_SIZE;
188
189 if (this->identifier.len <= PDP_REFERRAL_ID_HEADER_SIZE)
190 {
191 reader->destroy(reader);
192 return FAILED;
193 }
194 reader->read_uint8 (reader, &reserved);
195 reader->read_uint8 (reader, &this->protocol);
196 reader->read_uint16(reader, &this->port);
197 reader->read_data (reader, reader->remaining(reader), &this->fqdn);
198 this->fqdn = chunk_clone(this->fqdn);
199 reader->destroy(reader);
200 }
201 return SUCCESS;
202 }
203
204 METHOD(pb_tnc_msg_t, destroy, void,
205 private_pb_pdp_referral_msg_t *this)
206 {
207 free(this->encoding.ptr);
208 free(this->identifier.ptr);
209 free(this->fqdn.ptr);
210 free(this);
211 }
212
213 METHOD(pb_pdp_referral_msg_t, get_identifier_type, pen_type_t,
214 private_pb_pdp_referral_msg_t *this)
215 {
216 return this->identifier_type;
217 }
218
219 METHOD(pb_pdp_referral_msg_t, get_identifier, chunk_t,
220 private_pb_pdp_referral_msg_t *this)
221 {
222 return this->identifier;
223 }
224
225 METHOD(pb_pdp_referral_msg_t, get_fqdn, chunk_t,
226 private_pb_pdp_referral_msg_t *this, u_int8_t *protocol, u_int16_t *port)
227 {
228 if (protocol)
229 {
230 *protocol = this->protocol;
231 }
232 if (port)
233 {
234 *port = this->port;
235 }
236 return this->fqdn;
237 }
238
239 /**
240 * See header
241 */
242 pb_tnc_msg_t* pb_pdp_referral_msg_create(pen_type_t identifier_type,
243 chunk_t identifier)
244 {
245 private_pb_pdp_referral_msg_t *this;
246
247 INIT(this,
248 .public = {
249 .pb_interface = {
250 .get_type = _get_type,
251 .get_encoding = _get_encoding,
252 .build = _build,
253 .process = _process,
254 .destroy = _destroy,
255 },
256 .get_identifier_type = _get_identifier_type,
257 .get_identifier = _get_identifier,
258 },
259 .type = { PEN_TCG, PB_TCG_MSG_PDP_REFERRAL },
260 .identifier_type = identifier_type,
261 .identifier = chunk_clone(identifier),
262 );
263
264 return &this->public.pb_interface;
265 }
266
267 /**
268 * See header
269 */
270 pb_tnc_msg_t* pb_pdp_referral_msg_create_from_fqdn(chunk_t fqdn, u_int16_t port)
271 {
272 pb_tnc_msg_t *msg;
273 bio_writer_t *writer;
274 pen_type_t type = { PEN_TCG, PB_PDP_ID_FQDN };
275
276 writer = bio_writer_create(PDP_REFERRAL_ID_HEADER_SIZE + fqdn.len);
277 writer->write_uint8 (writer, PDP_REFERRAL_RESERVED);
278 writer->write_uint8 (writer, PDP_REFERRAL_PROTOCOL);
279 writer->write_uint16(writer, port);
280 writer->write_data (writer, fqdn);
281
282 msg = pb_pdp_referral_msg_create(type, writer->get_buf(writer));
283 writer->destroy(writer);
284
285 return msg;
286 }
287
288 /**
289 * See header
290 */
291 pb_tnc_msg_t *pb_pdp_referral_msg_create_from_data(chunk_t data)
292 {
293 private_pb_pdp_referral_msg_t *this;
294
295 INIT(this,
296 .public = {
297 .pb_interface = {
298 .get_type = _get_type,
299 .get_encoding = _get_encoding,
300 .build = _build,
301 .process = _process,
302 .destroy = _destroy,
303 },
304 .get_identifier_type = _get_identifier_type,
305 .get_identifier = _get_identifier,
306 .get_fqdn = _get_fqdn,
307 },
308 .type = { PEN_TCG, PB_TCG_MSG_PDP_REFERRAL },
309 .encoding = chunk_clone(data),
310 );
311
312 return &this->public.pb_interface;
313 }
314