2 * Copyright (C) 2008 Martin Willi
3 * 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
18 #include "ha_sync_message.h"
20 #include <arpa/inet.h>
24 #define ALLOCATION_BLOCK 64
26 typedef struct private_ha_sync_message_t private_ha_sync_message_t
;
29 * Private data of an ha_sync_message_t object.
31 struct private_ha_sync_message_t
{
34 * Public ha_sync_message_t interface.
36 ha_sync_message_t
public;
39 * Allocated size of buf
44 * Buffer containing encoded data
49 typedef struct ike_sa_id_encoding_t ike_sa_id_encoding_t
;
52 * Encoding if an ike_sa_id_t
54 struct ike_sa_id_encoding_t
{
55 u_int64_t initiator_spi
;
56 u_int64_t responder_spi
;
58 } __attribute__((packed
));
60 typedef struct identification_encoding_t identification_encoding_t
;
63 * Encoding of a identification_t
65 struct identification_encoding_t
{
69 } __attribute__((packed
));
71 typedef struct host_encoding_t host_encoding_t
;
74 * encoding of a host_t
76 struct host_encoding_t
{
80 } __attribute__((packed
));
83 * Implementation of ha_sync_message_t.get_type
85 static ha_sync_message_type_t
get_type(private_ha_sync_message_t
*this)
87 return this->buf
.ptr
[1];
91 * check for space in buffer, increase if necessary
93 static void check_buf(private_ha_sync_message_t
*this, size_t len
)
97 while (this->buf
.len
+ len
> this->allocated
)
99 this->allocated
+= ALLOCATION_BLOCK
;
104 this->buf
.ptr
= realloc(this->buf
.ptr
, this->allocated
);
109 * Implementation of ha_sync_message_t.add_attribute
111 static void add_attribute(private_ha_sync_message_t
*this,
112 ha_sync_message_attribute_t attribute
, ...)
117 check_buf(this, sizeof(u_int8_t
));
118 this->buf
.ptr
[this->buf
.len
] = attribute
;
119 this->buf
.len
+= sizeof(u_int8_t
);
121 va_start(args
, attribute
);
126 case HA_SYNC_IKE_REKEY_ID
:
128 ike_sa_id_encoding_t
*enc
;
131 id
= va_arg(args
, ike_sa_id_t
*);
132 check_buf(this, sizeof(ike_sa_id_encoding_t
));
133 enc
= (ike_sa_id_encoding_t
*)(this->buf
.ptr
+ this->buf
.len
);
134 this->buf
.len
+= sizeof(ike_sa_id_encoding_t
);
135 enc
->initiator
= id
->is_initiator(id
);
136 enc
->initiator_spi
= id
->get_initiator_spi(id
);
137 enc
->responder_spi
= id
->get_responder_spi(id
);
140 /* identification_t* */
141 case HA_SYNC_LOCAL_ID
:
142 case HA_SYNC_REMOTE_ID
:
145 identification_encoding_t
*enc
;
146 identification_t
*id
;
149 id
= va_arg(args
, identification_t
*);
150 data
= id
->get_encoding(id
);
151 check_buf(this, sizeof(identification_encoding_t
) + data
.len
);
152 enc
= (identification_encoding_t
*)(this->buf
.ptr
+ this->buf
.len
);
153 this->buf
.len
+= sizeof(identification_encoding_t
) + data
.len
;
154 enc
->type
= id
->get_type(id
);
156 memcpy(enc
->encoding
, data
.ptr
, data
.len
);
160 case HA_SYNC_LOCAL_ADDR
:
161 case HA_SYNC_REMOTE_ADDR
:
162 case HA_SYNC_LOCAL_VIP
:
163 case HA_SYNC_REMOTE_VIP
:
164 case HA_SYNC_ADDITIONAL_ADDR
:
166 host_encoding_t
*enc
;
170 host
= va_arg(args
, host_t
*);
171 data
= host
->get_address(host
);
172 check_buf(this, sizeof(host_encoding_t
) + data
.len
);
173 enc
= (host_encoding_t
*)(this->buf
.ptr
+ this->buf
.len
);
174 this->buf
.len
+= sizeof(host_encoding_t
) + data
.len
;
175 enc
->family
= host
->get_family(host
);
176 enc
->port
= htons(host
->get_port(host
));
177 memcpy(enc
->encoding
, data
.ptr
, data
.len
);
181 case HA_SYNC_CONFIG_NAME
:
185 str
= va_arg(args
, char*);
186 len
= strlen(str
) + 1;
187 check_buf(this, len
);
188 memcpy(this->buf
.ptr
+ this->buf
.len
, str
, len
);
189 this->buf
.len
+= len
;
193 case HA_SYNC_CONDITIONS
:
194 case HA_SYNC_EXTENSIONS
:
198 val
= va_arg(args
, u_int32_t
);
199 check_buf(this, sizeof(val
));
200 this->buf
.ptr
[this->buf
.len
] = htonl(val
);
201 this->buf
.len
+= sizeof(val
);
205 case HA_SYNC_NONCE_I
:
206 case HA_SYNC_NONCE_R
:
211 chunk
= va_arg(args
, chunk_t
);
212 check_buf(this, chunk
.len
);
213 memcpy(this->buf
.ptr
+ this->buf
.len
, chunk
.ptr
, chunk
.len
);
214 this->buf
.len
+= chunk
.len
;
219 DBG1(DBG_CFG
, "unable to encode, attribute %d unknown", attribute
);
220 this->buf
.len
-= sizeof(u_int8_t
);
228 * Implementation of ha_sync_message_t.create_attribute_enumerator
230 static enumerator_t
* create_attribute_enumerator(private_ha_sync_message_t
*this)
232 return enumerator_create_empty();
236 * Implementation of ha_sync_message_t.get_encoding
238 static chunk_t
get_encoding(private_ha_sync_message_t
*this)
244 * Implementation of ha_sync_message_t.destroy.
246 static void destroy(private_ha_sync_message_t
*this)
253 static private_ha_sync_message_t
*ha_sync_message_create_generic()
255 private_ha_sync_message_t
*this = malloc_thing(private_ha_sync_message_t
);
257 this->public.get_type
= (ha_sync_message_type_t(*)(ha_sync_message_t
*))get_type
;
258 this->public.add_attribute
= (void(*)(ha_sync_message_t
*, ha_sync_message_attribute_t attribute
, ...))add_attribute
;
259 this->public.create_attribute_enumerator
= (enumerator_t
*(*)(ha_sync_message_t
*))create_attribute_enumerator
;
260 this->public.get_encoding
= (chunk_t(*)(ha_sync_message_t
*))get_encoding
;
261 this->public.destroy
= (void(*)(ha_sync_message_t
*))destroy
;
269 ha_sync_message_t
*ha_sync_message_create(ha_sync_message_type_t type
)
271 private_ha_sync_message_t
*this = ha_sync_message_create_generic();
273 this->allocated
= ALLOCATION_BLOCK
;
274 this->buf
.ptr
= malloc(this->allocated
);
276 this->buf
.ptr
[0] = HA_SYNC_MESSAGE_VERSION
;
277 this->buf
.ptr
[1] = type
;
279 return &this->public;
285 ha_sync_message_t
*ha_sync_message_parse(chunk_t data
)
287 private_ha_sync_message_t
*this;
291 DBG1(DBG_CFG
, "HA sync message too short");
294 if (data
.ptr
[0] != HA_SYNC_MESSAGE_VERSION
)
296 DBG1(DBG_CFG
, "HA sync message has version %d, expected %d",
297 data
.ptr
[0], HA_SYNC_MESSAGE_VERSION
);
301 this = ha_sync_message_create_generic();
302 this->buf
= chunk_clone(data
);
303 this->allocated
= this->buf
.len
;
305 return &this->public;