2 * Copyright (C) 2006 Mike McCauley (mikem@open.com.au)
3 * Copyright (C) 2010 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
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>.
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
16 #include "imc_imv_msg.h"
18 #include <tnc/tnccs/tnccs.h>
20 #include <utils/lexparser.h>
21 #include <utils/debug.h>
23 typedef struct private_imc_imv_msg_t private_imc_imv_msg_t
;
25 #define BYTES_PER_LINE 57
28 * Private data of a imc_imv_msg_t object.
31 struct private_imc_imv_msg_t
{
33 * Public imc_imv_msg_t interface.
40 tnccs_msg_type_t type
;
43 * XML-encoded message node
48 * IMC-IMV message type
50 TNC_MessageType msg_type
;
53 * IMC-IMV message body
60 * Encodes message data into multiple base64-encoded lines
62 static chunk_t
encode_base64(chunk_t data
)
66 size_t b64_chars
, b64_lines
;
68 /* handle empty message data object */
71 encoding
= chunk_alloc(1);
76 /* compute and allocate maximum size of base64 object */
77 b64_chars
= 4 * ((data
.len
+ 2) / 3);
78 b64_lines
= (data
.len
+ BYTES_PER_LINE
- 1) / BYTES_PER_LINE
;
79 encoding
= chunk_alloc(b64_chars
+ b64_lines
);
85 chunk_t data_line
, b64_line
;
87 data_line
= chunk_create(data
.ptr
, min(data
.len
, BYTES_PER_LINE
));
88 data
.ptr
+= data_line
.len
;
89 data
.len
-= data_line
.len
;
90 b64_line
= chunk_to_base64(data_line
, pos
);
95 /* terminate last line with NULL character instead of newline */
102 * Decodes message data from multiple base64-encoded lines
104 static chunk_t
decode_base64(chunk_t data
)
106 chunk_t decoding
, data_line
, b64_line
;
109 /* compute and allocate maximum size of decoded message data */
110 decoding
= chunk_alloc(3 * ((data
.len
+ 3) / 4));
114 while (fetchline(&data
, &b64_line
))
116 data_line
= chunk_from_base64(b64_line
, pos
);
117 pos
+= data_line
.len
;
118 decoding
.len
+= data_line
.len
;
124 METHOD(tnccs_msg_t
, get_type
, tnccs_msg_type_t
,
125 private_imc_imv_msg_t
*this)
130 METHOD(tnccs_msg_t
, get_node
, xmlNodePtr
,
131 private_imc_imv_msg_t
*this)
136 METHOD(tnccs_msg_t
, destroy
, void,
137 private_imc_imv_msg_t
*this)
139 free(this->msg_body
.ptr
);
143 METHOD(imc_imv_msg_t
, get_msg_type
, TNC_MessageType
,
144 private_imc_imv_msg_t
*this)
146 return this->msg_type
;
149 METHOD(imc_imv_msg_t
, get_msg_body
, chunk_t
,
150 private_imc_imv_msg_t
*this)
152 return this->msg_body
;
158 tnccs_msg_t
*imc_imv_msg_create_from_node(xmlNodePtr node
, linked_list_t
*errors
)
160 private_imc_imv_msg_t
*this;
168 .tnccs_msg_interface
= {
169 .get_type
= _get_type
,
170 .get_node
= _get_node
,
173 .get_msg_type
= _get_msg_type
,
174 .get_msg_body
= _get_msg_body
,
181 cur
= node
->xmlChildrenNode
;
184 if (streq(cur
->name
, "Type") && cur
->ns
== ns
)
186 content
= xmlNodeGetContent(cur
);
187 this->msg_type
= strtoul(content
, NULL
, 16);
190 else if (streq(cur
->name
, "Base64") && cur
->ns
== ns
)
192 content
= xmlNodeGetContent(cur
);
193 b64_body
= chunk_create(content
, strlen(content
));
194 this->msg_body
= decode_base64(b64_body
);
200 return &this->public.tnccs_msg_interface
;
206 tnccs_msg_t
*imc_imv_msg_create(TNC_MessageType msg_type
, chunk_t msg_body
)
208 private_imc_imv_msg_t
*this;
210 char buf
[10]; /* big enough for hex-encoded message type */
215 .tnccs_msg_interface
= {
216 .get_type
= _get_type
,
217 .get_node
= _get_node
,
220 .get_msg_type
= _get_msg_type
,
221 .get_msg_body
= _get_msg_body
,
224 .node
= xmlNewNode(NULL
, "IMC-IMV-Message"),
225 .msg_type
= msg_type
,
226 .msg_body
= chunk_clone(msg_body
),
229 /* add the message type number in hex */
230 n
= xmlNewNode(NULL
, "Type");
231 snprintf(buf
, 10, "%08x", this->msg_type
);
232 xmlNodeSetContent(n
, buf
);
233 xmlAddChild(this->node
, n
);
235 /* encode the message as a Base64 node */
236 n
= xmlNewNode(NULL
, "Base64");
237 b64_body
= encode_base64(this->msg_body
);
238 xmlNodeSetContent(n
, b64_body
.ptr
);
239 xmlAddChild(this->node
, n
);
242 return &this->public.tnccs_msg_interface
;