]> git.ipfire.org Git - people/ms/strongswan.git/blame - src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c
Moved tnc-tnccs, tnc-imc, tnccs-11, tnccs-20 and tnccs-dynamic libcharon plugins...
[people/ms/strongswan.git] / src / libtnccs / plugins / tnccs_20 / batch / pb_tnc_batch.c
CommitLineData
4333c48a
AS
1/*
2 * Copyright (C) 2010 Sansar Choinyanbuu
22e97e4f 3 * Copyright (C) 2010-2012 Andreas Steffen
4333c48a
AS
4 * HSR Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
4333c48a 17#include "pb_tnc_batch.h"
54eb669d 18#include "messages/pb_error_msg.h"
5988fc0d 19#include "state_machine/pb_tnc_state_machine.h"
4333c48a 20
f0a8bf47
AS
21#include <tnc/tnccs/tnccs.h>
22
12642a68 23#include <collections/linked_list.h>
7e432eff
AS
24#include <bio/bio_writer.h>
25#include <bio/bio_reader.h>
7c4d4d20 26#include <pen/pen.h>
f05b4272 27#include <utils/debug.h>
4333c48a 28
4333c48a
AS
29ENUM(pb_tnc_batch_type_names, PB_BATCH_CDATA, PB_BATCH_CLOSE,
30 "CDATA",
31 "SDATA",
32 "RESULT",
33 "CRETRY",
34 "SRETRY",
35 "CLOSE"
36);
37
38typedef struct private_pb_tnc_batch_t private_pb_tnc_batch_t;
39
40/**
41 * PB-Batch Header (see section 4.1 of RFC 5793)
42 *
43 * 0 1 2 3
44 * 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
45 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46 * | Version |D| Reserved | B-Type|
47 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48 * | Batch Length |
49 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 */
51
52#define PB_TNC_BATCH_FLAG_NONE 0x00
53#define PB_TNC_BATCH_FLAG_D (1<<7)
a5c79d01 54#define PB_TNC_BATCH_HEADER_SIZE 8
4333c48a
AS
55
56/**
57 * PB-TNC Message (see section 4.2 of RFC 5793)
58 *
59 * 0 1 2 3
60 * 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
61 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62 * | Flags | PB-TNC Vendor ID |
63 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64 * | PB-TNC Message Type |
65 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66 * | PB-TNC Message Length |
67 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68 * | PB-TNC Message Value (Variable Length) |
69 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70 */
71
72#define PB_TNC_FLAG_NONE 0x00
73#define PB_TNC_FLAG_NOSKIP (1<<7)
a5c79d01 74#define PB_TNC_HEADER_SIZE 12
4333c48a
AS
75
76#define PB_TNC_RESERVED_MSG_TYPE 0xffffffff
77
78/**
79 * Private data of a pb_tnc_batch_t object.
80 *
81 */
82struct private_pb_tnc_batch_t {
83 /**
54eb669d 84 * Public pb_pa_msg_t interface.
4333c48a
AS
85 */
86 pb_tnc_batch_t public;
87
88 /**
89 * TNCC if TRUE, TNCS if FALSE
90 */
91 bool is_server;
92
93 /**
94 * PB-TNC Batch type
95 */
96 pb_tnc_batch_type_t type;
97
a5c79d01
AS
98 /**
99 * Current PB-TNC Batch size
100 */
101 size_t batch_len;
102
103 /**
104 * Maximum PB-TNC Batch size
105 */
106 size_t max_batch_len;
107
4333c48a
AS
108 /**
109 * linked list of PB-TNC messages
110 */
111 linked_list_t *messages;
112
113 /**
114 * linked list of PB-TNC error messages
115 */
116 linked_list_t *errors;
117
118 /**
119 * Encoded message
120 */
121 chunk_t encoding;
122
123 /**
124 * Offset into encoding (used for error reporting)
125 */
54eb669d 126 u_int32_t offset;
4333c48a
AS
127};
128
129METHOD(pb_tnc_batch_t, get_type, pb_tnc_batch_type_t,
130 private_pb_tnc_batch_t *this)
131{
132 return this->type;
133}
134
135METHOD(pb_tnc_batch_t, get_encoding, chunk_t,
136 private_pb_tnc_batch_t *this)
137{
138 return this->encoding;
139}
140
a5c79d01 141METHOD(pb_tnc_batch_t, add_msg, bool,
54eb669d 142 private_pb_tnc_batch_t *this, pb_tnc_msg_t* msg)
4333c48a 143{
a5c79d01
AS
144 chunk_t msg_value;
145 size_t msg_len;
146
147 msg->build(msg);
148 msg_value = msg->get_encoding(msg);
149 msg_len = PB_TNC_HEADER_SIZE + msg_value.len;
150
151 if (this->batch_len + msg_len > this->max_batch_len)
152 {
153 /* message just does not fit into this batch */
154 return FALSE;
155 }
156 this->batch_len += msg_len;
157
41216e65 158 DBG2(DBG_TNC, "adding %N message", pb_tnc_msg_type_names,
4ca368d2 159 msg->get_type(msg));
4333c48a 160 this->messages->insert_last(this->messages, msg);
a5c79d01 161 return TRUE;
4333c48a
AS
162}
163
164METHOD(pb_tnc_batch_t, build, void,
165 private_pb_tnc_batch_t *this)
166{
a5c79d01 167 u_int32_t msg_len;
4333c48a
AS
168 chunk_t msg_value;
169 enumerator_t *enumerator;
170 pb_tnc_msg_type_t msg_type;
54eb669d 171 pb_tnc_msg_t *msg;
7e432eff 172 bio_writer_t *writer;
4333c48a 173
4333c48a 174 /* build PB-TNC batch header */
12642a68 175 writer = bio_writer_create(this->batch_len);
4333c48a
AS
176 writer->write_uint8 (writer, PB_TNC_VERSION);
177 writer->write_uint8 (writer, this->is_server ?
178 PB_TNC_BATCH_FLAG_D : PB_TNC_BATCH_FLAG_NONE);
179 writer->write_uint16(writer, this->type);
12642a68 180 writer->write_uint32(writer, this->batch_len);
4333c48a
AS
181
182 /* build PB-TNC messages */
183 enumerator = this->messages->create_enumerator(this->messages);
184 while (enumerator->enumerate(enumerator, &msg))
185 {
54eb669d
AS
186 u_int8_t flags = PB_TNC_FLAG_NONE;
187
4333c48a
AS
188 /* build PB-TNC message */
189 msg_value = msg->get_encoding(msg);
190 msg_len = PB_TNC_HEADER_SIZE + msg_value.len;
191 msg_type = msg->get_type(msg);
54eb669d 192 if (pb_tnc_msg_infos[msg_type].has_noskip_flag)
4333c48a 193 {
54eb669d
AS
194 flags |= PB_TNC_FLAG_NOSKIP;
195 }
4333c48a 196 writer->write_uint8 (writer, flags);
425a3a26 197 writer->write_uint24(writer, PEN_IETF);
4333c48a
AS
198 writer->write_uint32(writer, msg_type);
199 writer->write_uint32(writer, msg_len);
200 writer->write_data (writer, msg_value);
201 }
202 enumerator->destroy(enumerator);
203
1a9dee5d 204 this->encoding = writer->extract_buf(writer);
4333c48a
AS
205 writer->destroy(writer);
206}
207
208static status_t process_batch_header(private_pb_tnc_batch_t *this,
5988fc0d 209 pb_tnc_state_machine_t *state_machine)
4333c48a 210{
7e432eff 211 bio_reader_t *reader;
54eb669d
AS
212 pb_tnc_msg_t *msg;
213 pb_error_msg_t *err_msg;
4333c48a
AS
214 u_int8_t version, flags, reserved, type;
215 u_int32_t batch_len;
68fada37 216 bool directionality;
4333c48a
AS
217
218 if (this->encoding.len < PB_TNC_BATCH_HEADER_SIZE)
219 {
220 DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC batch header",
221 this->encoding.len);
425a3a26 222 msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
54eb669d 223 PB_ERROR_INVALID_PARAMETER, 0);
4333c48a
AS
224 goto fatal;
225 }
226
7e432eff 227 reader = bio_reader_create(this->encoding);
4333c48a
AS
228 reader->read_uint8 (reader, &version);
229 reader->read_uint8 (reader, &flags);
230 reader->read_uint8 (reader, &reserved);
231 reader->read_uint8 (reader, &type);
232 reader->read_uint32(reader, &batch_len);
233 reader->destroy(reader);
234
235 /* Version */
236 if (version != PB_TNC_VERSION)
237 {
c56667f1 238 DBG1(DBG_TNC, "unsupported TNCCS batch version 0x%02x", version);
425a3a26 239 msg = pb_error_msg_create(TRUE, PEN_IETF,
54eb669d
AS
240 PB_ERROR_VERSION_NOT_SUPPORTED);
241 err_msg = (pb_error_msg_t*)msg;
4333c48a
AS
242 err_msg->set_bad_version(err_msg, version);
243 goto fatal;
244 }
245
246 /* Directionality */
247 directionality = (flags & PB_TNC_BATCH_FLAG_D) != PB_TNC_BATCH_FLAG_NONE;
248 if (directionality == this->is_server)
249 {
41216e65
AS
250 DBG1(DBG_TNC, "wrong Directionality: batch is from a PB %s",
251 directionality ? "server" : "client");
425a3a26 252 msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
54eb669d 253 PB_ERROR_INVALID_PARAMETER, 1);
4333c48a
AS
254 goto fatal;
255 }
256
257 /* Batch Type */
258 this->type = type & 0x0F;
259 if (this->type > PB_BATCH_ROOF)
260 {
41216e65 261 DBG1(DBG_TNC, "unknown PB-TNC batch type: %d", this->type);
425a3a26 262 msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
54eb669d 263 PB_ERROR_INVALID_PARAMETER, 3);
4333c48a
AS
264 goto fatal;
265 }
68fada37 266
5988fc0d 267 if (!state_machine->receive_batch(state_machine, this->type))
4333c48a 268 {
41216e65 269 DBG1(DBG_TNC, "unexpected PB-TNC batch type: %N",
4333c48a 270 pb_tnc_batch_type_names, this->type);
425a3a26 271 msg = pb_error_msg_create(TRUE, PEN_IETF,
54eb669d 272 PB_ERROR_UNEXPECTED_BATCH_TYPE);
4333c48a
AS
273 goto fatal;
274 }
b8b678a5
AS
275 DBG1(DBG_TNC, "processing PB-TNC %N batch", pb_tnc_batch_type_names,
276 this->type);
4333c48a
AS
277
278 /* Batch Length */
279 if (this->encoding.len != batch_len)
280 {
281 DBG1(DBG_TNC, "%u bytes of data is not equal to batch length of %u bytes",
282 this->encoding.len, batch_len);
425a3a26 283 msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
54eb669d 284 PB_ERROR_INVALID_PARAMETER, 4);
4333c48a
AS
285 goto fatal;
286 }
287
288 this->offset = PB_TNC_BATCH_HEADER_SIZE;
b8b678a5
AS
289
290 /* Register an empty CDATA batch with the state machine */
291 if (this->type == PB_BATCH_CDATA)
292 {
293 state_machine->set_empty_cdata(state_machine,
294 this->offset == this->encoding.len);
295 }
4333c48a
AS
296 return SUCCESS;
297
298fatal:
299 this->errors->insert_last(this->errors, msg);
12642a68 300 return FAILED;
4333c48a
AS
301}
302
54eb669d 303static status_t process_tnc_msg(private_pb_tnc_batch_t *this)
4333c48a 304{
7e432eff 305 bio_reader_t *reader;
54eb669d 306 pb_tnc_msg_t *pb_tnc_msg, *msg;
4333c48a 307 u_int8_t flags;
54eb669d 308 u_int32_t vendor_id, msg_type, msg_len, offset;
4333c48a 309 chunk_t data, msg_value;
54eb669d 310 bool noskip_flag;
4333c48a
AS
311 status_t status;
312
313 data = chunk_skip(this->encoding, this->offset);
314
315 if (data.len < PB_TNC_HEADER_SIZE)
316 {
317 DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC message header",
318 data.len);
425a3a26 319 msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
54eb669d 320 PB_ERROR_INVALID_PARAMETER, this->offset);
4333c48a
AS
321 goto fatal;
322 }
323
7e432eff 324 reader = bio_reader_create(data);
4333c48a
AS
325 reader->read_uint8 (reader, &flags);
326 reader->read_uint24(reader, &vendor_id);
327 reader->read_uint32(reader, &msg_type);
328 reader->read_uint32(reader, &msg_len);
329 reader->destroy(reader);
330
54eb669d 331 noskip_flag = (flags & PB_TNC_FLAG_NOSKIP) != PB_TNC_FLAG_NONE;
12642a68 332
4333c48a
AS
333 if (msg_len > data.len)
334 {
335 DBG1(DBG_TNC, "%u bytes insufficient to parse PB-TNC message", data.len);
425a3a26 336 msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
54eb669d 337 PB_ERROR_INVALID_PARAMETER, this->offset + 8);
4333c48a
AS
338 goto fatal;
339 }
340
425a3a26 341 if (vendor_id == PEN_RESERVED)
4333c48a 342 {
425a3a26
AS
343 DBG1(DBG_TNC, "Vendor ID 0x%06x is reserved", PEN_RESERVED);
344 msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
54eb669d 345 PB_ERROR_INVALID_PARAMETER, this->offset + 1);
4333c48a
AS
346 goto fatal;
347
348 }
349
350 if (msg_type == PB_TNC_RESERVED_MSG_TYPE)
351 {
41216e65 352 DBG1(DBG_TNC, "PB-TNC message Type 0x%08x is reserved",
4333c48a 353 PB_TNC_RESERVED_MSG_TYPE);
425a3a26 354 msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
54eb669d 355 PB_ERROR_INVALID_PARAMETER, this->offset + 4);
4333c48a
AS
356 goto fatal;
357 }
358
54eb669d 359
425a3a26 360 if (vendor_id != PEN_IETF || msg_type > PB_MSG_ROOF)
4333c48a 361 {
54eb669d
AS
362 if (msg_len < PB_TNC_HEADER_SIZE)
363 {
364 DBG1(DBG_TNC, "%u bytes too small for PB-TNC message length",
365 msg_len);
425a3a26 366 msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
54eb669d
AS
367 PB_ERROR_INVALID_PARAMETER, this->offset + 8);
368 goto fatal;
369 }
370
371 if (noskip_flag)
4333c48a 372 {
41216e65 373 DBG1(DBG_TNC, "reject PB-TNC message (Vendor ID 0x%06x / "
4ca368d2 374 "Type 0x%08x)", vendor_id, msg_type);
425a3a26 375 msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
54eb669d 376 PB_ERROR_UNSUPPORTED_MANDATORY_MSG, this->offset);
4333c48a
AS
377 goto fatal;
378 }
379 else
380 {
41216e65 381 DBG1(DBG_TNC, "ignore PB-TNC message (Vendor ID 0x%06x / "
4ca368d2 382 "Type 0x%08x)", vendor_id, msg_type);
4333c48a 383 this->offset += msg_len;
af1e3ff5 384 return SUCCESS;
4333c48a
AS
385 }
386 }
54eb669d
AS
387 else
388 {
0f7cb0ca
AS
389 if (msg_type == PB_MSG_EXPERIMENTAL && noskip_flag)
390 {
391 DBG1(DBG_TNC, "reject PB-Experimental message with NOSKIP flag set");
392 msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
393 PB_ERROR_UNSUPPORTED_MANDATORY_MSG, this->offset);
394 goto fatal;
395 }
54eb669d
AS
396 if (pb_tnc_msg_infos[msg_type].has_noskip_flag != TRUE_OR_FALSE &&
397 pb_tnc_msg_infos[msg_type].has_noskip_flag != noskip_flag)
398 {
41216e65 399 DBG1(DBG_TNC, "%N message must%s have NOSKIP flag set",
54eb669d
AS
400 pb_tnc_msg_type_names, msg_type,
401 pb_tnc_msg_infos[msg_type].has_noskip_flag ? "" : " not");
425a3a26 402 msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
54eb669d
AS
403 PB_ERROR_INVALID_PARAMETER, this->offset);
404 goto fatal;
405 }
4333c48a 406
54eb669d
AS
407 if (msg_len < pb_tnc_msg_infos[msg_type].min_size ||
408 (pb_tnc_msg_infos[msg_type].exact_size &&
409 msg_len != pb_tnc_msg_infos[msg_type].min_size))
410 {
41216e65 411 DBG1(DBG_TNC, "%N message length must be %s %u bytes but is %u bytes",
54eb669d
AS
412 pb_tnc_msg_type_names, msg_type,
413 pb_tnc_msg_infos[msg_type].exact_size ? "exactly" : "at least",
414 pb_tnc_msg_infos[msg_type].min_size, msg_len);
425a3a26 415 msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
54eb669d
AS
416 PB_ERROR_INVALID_PARAMETER, this->offset);
417 goto fatal;
418 }
419 }
420
421 if (pb_tnc_msg_infos[msg_type].in_result_batch &&
422 this->type != PB_BATCH_RESULT)
7e7efa64 423 {
af1e3ff5
AS
424 if (this->is_server)
425 {
41216e65 426 DBG1(DBG_TNC,"reject %N message received from a PB-TNC client",
af1e3ff5 427 pb_tnc_msg_type_names, msg_type);
425a3a26 428 msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
54eb669d 429 PB_ERROR_INVALID_PARAMETER, this->offset);
af1e3ff5
AS
430 goto fatal;
431 }
432 else
433 {
41216e65 434 DBG1(DBG_TNC,"ignore %N message not received within RESULT batch",
af1e3ff5
AS
435 pb_tnc_msg_type_names, msg_type);
436 this->offset += msg_len;
437 return SUCCESS;
438 }
7e7efa64
AS
439 }
440
41216e65 441 DBG2(DBG_TNC, "processing %N message (%u bytes)", pb_tnc_msg_type_names,
4333c48a
AS
442 msg_type, msg_len);
443 data.len = msg_len;
4333c48a 444 msg_value = chunk_skip(data, PB_TNC_HEADER_SIZE);
54eb669d 445 pb_tnc_msg = pb_tnc_msg_create_from_data(msg_type, msg_value);
4333c48a 446
54eb669d
AS
447 status = pb_tnc_msg->process(pb_tnc_msg, &offset);
448 if (status == FAILED || status == VERIFY_ERROR)
449 {
425a3a26 450 msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
a96d9abf 451 PB_ERROR_INVALID_PARAMETER, this->offset + offset);
54eb669d
AS
452 this->errors->insert_last(this->errors, msg);
453 }
4333c48a
AS
454 if (status == FAILED)
455 {
456 pb_tnc_msg->destroy(pb_tnc_msg);
457 return FAILED;
458 }
459 this->messages->insert_last(this->messages, pb_tnc_msg);
460 this->offset += msg_len;
54eb669d 461 return status;
4333c48a
AS
462
463fatal:
464 this->errors->insert_last(this->errors, msg);
12642a68 465 return FAILED;
4333c48a
AS
466}
467
468METHOD(pb_tnc_batch_t, process, status_t,
5988fc0d 469 private_pb_tnc_batch_t *this, pb_tnc_state_machine_t *state_machine)
4333c48a
AS
470{
471 status_t status;
472
5988fc0d 473 status = process_batch_header(this, state_machine);
af1e3ff5 474 if (status != SUCCESS)
4333c48a
AS
475 {
476 return FAILED;
477 }
b8b678a5 478
4333c48a
AS
479 while (this->offset < this->encoding.len)
480 {
54eb669d 481 switch (process_tnc_msg(this))
4333c48a 482 {
af1e3ff5
AS
483 case FAILED:
484 return FAILED;
485 case VERIFY_ERROR:
486 status = VERIFY_ERROR;
487 break;
488 case SUCCESS:
489 default:
490 break;
4333c48a
AS
491 }
492 }
af1e3ff5 493 return status;
4333c48a
AS
494}
495
496METHOD(pb_tnc_batch_t, create_msg_enumerator, enumerator_t*,
497 private_pb_tnc_batch_t *this)
498{
499 return this->messages->create_enumerator(this->messages);
500}
501
502METHOD(pb_tnc_batch_t, create_error_enumerator, enumerator_t*,
503 private_pb_tnc_batch_t *this)
504{
505 return this->errors->create_enumerator(this->errors);
506}
507
508METHOD(pb_tnc_batch_t, destroy, void,
509 private_pb_tnc_batch_t *this)
510{
511 this->messages->destroy_offset(this->messages,
54eb669d 512 offsetof(pb_tnc_msg_t, destroy));
4333c48a 513 this->errors->destroy_offset(this->errors,
54eb669d 514 offsetof(pb_tnc_msg_t, destroy));
4333c48a
AS
515 free(this->encoding.ptr);
516 free(this);
517}
518
519/**
520 * See header
521 */
a5c79d01
AS
522pb_tnc_batch_t* pb_tnc_batch_create(bool is_server, pb_tnc_batch_type_t type,
523 size_t max_batch_len)
4333c48a
AS
524{
525 private_pb_tnc_batch_t *this;
526
527 INIT(this,
528 .public = {
529 .get_type = _get_type,
530 .get_encoding = _get_encoding,
54eb669d 531 .add_msg = _add_msg,
4333c48a
AS
532 .build = _build,
533 .process = _process,
534 .create_msg_enumerator = _create_msg_enumerator,
535 .create_error_enumerator = _create_error_enumerator,
536 .destroy = _destroy,
537 },
538 .is_server = is_server,
539 .type = type,
a5c79d01
AS
540 .max_batch_len = max_batch_len,
541 .batch_len = PB_TNC_BATCH_HEADER_SIZE,
4333c48a
AS
542 .messages = linked_list_create(),
543 .errors = linked_list_create(),
544 );
545
41216e65 546 DBG2(DBG_TNC, "creating PB-TNC %N batch", pb_tnc_batch_type_names, type);
4333c48a
AS
547
548 return &this->public;
549}
550
551/**
552 * See header
553 */
554pb_tnc_batch_t* pb_tnc_batch_create_from_data(bool is_server, chunk_t data)
555{
556 private_pb_tnc_batch_t *this;
557
558 INIT(this,
559 .public = {
560 .get_type = _get_type,
561 .get_encoding = _get_encoding,
54eb669d 562 .add_msg = _add_msg,
4333c48a
AS
563 .build = _build,
564 .process = _process,
565 .create_msg_enumerator = _create_msg_enumerator,
566 .create_error_enumerator = _create_error_enumerator,
567 .destroy = _destroy,
568 },
569 .is_server = is_server,
570 .messages = linked_list_create(),
571 .errors = linked_list_create(),
572 .encoding = chunk_clone(data),
573 );
574
575 return &this->public;
576}
577