]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/plugins/ha/ha_message.c
ha: Add auth method for HA IKEv1 key derivation
[thirdparty/strongswan.git] / src / libcharon / plugins / ha / ha_message.c
CommitLineData
e5e91eec
MW
1/*
2 * Copyright (C) 2008 Martin Willi
1b671669 3 * HSR Hochschule fuer Technik Rapperswil
e5e91eec
MW
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.
e5e91eec
MW
14 */
15
190edaf5
MW
16#define _GNU_SOURCE
17#include <string.h>
e5e91eec
MW
18#include <arpa/inet.h>
19
d8748966 20#include "ha_message.h"
190edaf5 21
e5e91eec
MW
22#include <daemon.h>
23
12ec91ba
MW
24#define ALLOCATION_BLOCK 64
25
d8748966 26typedef struct private_ha_message_t private_ha_message_t;
e5e91eec
MW
27
28/**
d8748966 29 * Private data of an ha_message_t object.
e5e91eec 30 */
d8748966 31struct private_ha_message_t {
e5e91eec
MW
32
33 /**
d8748966 34 * Public ha_message_t interface.
e5e91eec 35 */
d8748966 36 ha_message_t public;
e5e91eec
MW
37
38 /**
12ec91ba 39 * Allocated size of buf
e5e91eec
MW
40 */
41 size_t allocated;
42
43 /**
44 * Buffer containing encoded data
45 */
46 chunk_t buf;
47};
48
c8531b7e 49ENUM(ha_message_type_names, HA_IKE_ADD, HA_IKE_IV,
f2eebed2
MW
50 "IKE_ADD",
51 "IKE_UPDATE",
52 "IKE_MID_INITIATOR",
53 "IKE_MID_RESPONDER",
54 "IKE_DELETE",
55 "CHILD_ADD",
56 "CHILD_DELETE",
57 "SEGMENT_DROP",
58 "SEGMENT_TAKE",
59 "STATUS",
60 "RESYNC",
c8531b7e 61 "IKE_IV",
f2eebed2
MW
62);
63
12ec91ba
MW
64typedef struct ike_sa_id_encoding_t ike_sa_id_encoding_t;
65
66/**
67 * Encoding if an ike_sa_id_t
68 */
69struct ike_sa_id_encoding_t {
b12c53ce
AS
70 uint8_t ike_version;
71 uint64_t initiator_spi;
72 uint64_t responder_spi;
73 uint8_t initiator;
12ec91ba
MW
74} __attribute__((packed));
75
76typedef struct identification_encoding_t identification_encoding_t;
77
78/**
79 * Encoding of a identification_t
80 */
81struct identification_encoding_t {
b12c53ce
AS
82 uint8_t type;
83 uint8_t len;
12ec91ba
MW
84 char encoding[];
85} __attribute__((packed));
86
87typedef struct host_encoding_t host_encoding_t;
88
89/**
90 * encoding of a host_t
91 */
92struct host_encoding_t {
b12c53ce
AS
93 uint16_t port;
94 uint8_t family;
12ec91ba
MW
95 char encoding[];
96} __attribute__((packed));
97
7999be5b
MW
98typedef struct ts_encoding_t ts_encoding_t;
99
100/**
101 * encoding of a traffic_selector_t
102 */
103struct ts_encoding_t {
b12c53ce
AS
104 uint8_t type;
105 uint8_t protocol;
106 uint16_t from_port;
107 uint16_t to_port;
108 uint8_t dynamic;
7999be5b
MW
109 char encoding[];
110} __attribute__((packed));
111
00c1bd06
MW
112METHOD(ha_message_t, get_type, ha_message_type_t,
113 private_ha_message_t *this)
e5e91eec
MW
114{
115 return this->buf.ptr[1];
116}
117
118/**
119 * check for space in buffer, increase if necessary
120 */
d8748966 121static void check_buf(private_ha_message_t *this, size_t len)
e5e91eec 122{
12ec91ba
MW
123 int increased = 0;
124
e5e91eec
MW
125 while (this->buf.len + len > this->allocated)
126 { /* double size */
12ec91ba
MW
127 this->allocated += ALLOCATION_BLOCK;
128 increased++;
129 }
130 if (increased)
131 {
e5e91eec
MW
132 this->buf.ptr = realloc(this->buf.ptr, this->allocated);
133 }
134}
135
00c1bd06
MW
136METHOD(ha_message_t, add_attribute, void,
137 private_ha_message_t *this, ha_message_attribute_t attribute, ...)
e5e91eec
MW
138{
139 size_t len;
12ec91ba 140 va_list args;
e5e91eec 141
b12c53ce 142 check_buf(this, sizeof(uint8_t));
e5e91eec 143 this->buf.ptr[this->buf.len] = attribute;
b12c53ce 144 this->buf.len += sizeof(uint8_t);
e5e91eec 145
12ec91ba 146 va_start(args, attribute);
e5e91eec
MW
147 switch (attribute)
148 {
12ec91ba 149 /* ike_sa_id_t* */
d8748966
MW
150 case HA_IKE_ID:
151 case HA_IKE_REKEY_ID:
12ec91ba
MW
152 {
153 ike_sa_id_encoding_t *enc;
154 ike_sa_id_t *id;
155
156 id = va_arg(args, ike_sa_id_t*);
157 check_buf(this, sizeof(ike_sa_id_encoding_t));
158 enc = (ike_sa_id_encoding_t*)(this->buf.ptr + this->buf.len);
159 this->buf.len += sizeof(ike_sa_id_encoding_t);
160 enc->initiator = id->is_initiator(id);
1726795f 161 enc->ike_version = id->get_ike_version(id);
12ec91ba
MW
162 enc->initiator_spi = id->get_initiator_spi(id);
163 enc->responder_spi = id->get_responder_spi(id);
e5e91eec 164 break;
12ec91ba
MW
165 }
166 /* identification_t* */
d8748966
MW
167 case HA_LOCAL_ID:
168 case HA_REMOTE_ID:
fa4f71c8 169 case HA_REMOTE_EAP_ID:
12ec91ba
MW
170 {
171 identification_encoding_t *enc;
172 identification_t *id;
173 chunk_t data;
174
175 id = va_arg(args, identification_t*);
176 data = id->get_encoding(id);
177 check_buf(this, sizeof(identification_encoding_t) + data.len);
178 enc = (identification_encoding_t*)(this->buf.ptr + this->buf.len);
179 this->buf.len += sizeof(identification_encoding_t) + data.len;
180 enc->type = id->get_type(id);
181 enc->len = data.len;
182 memcpy(enc->encoding, data.ptr, data.len);
e5e91eec 183 break;
12ec91ba
MW
184 }
185 /* host_t* */
d8748966
MW
186 case HA_LOCAL_ADDR:
187 case HA_REMOTE_ADDR:
188 case HA_LOCAL_VIP:
189 case HA_REMOTE_VIP:
94bbc602 190 case HA_PEER_ADDR:
12ec91ba
MW
191 {
192 host_encoding_t *enc;
193 host_t *host;
194 chunk_t data;
195
196 host = va_arg(args, host_t*);
197 data = host->get_address(host);
198 check_buf(this, sizeof(host_encoding_t) + data.len);
199 enc = (host_encoding_t*)(this->buf.ptr + this->buf.len);
200 this->buf.len += sizeof(host_encoding_t) + data.len;
201 enc->family = host->get_family(host);
202 enc->port = htons(host->get_port(host));
203 memcpy(enc->encoding, data.ptr, data.len);
e5e91eec 204 break;
12ec91ba
MW
205 }
206 /* char* */
d8748966 207 case HA_CONFIG_NAME:
12ec91ba
MW
208 {
209 char *str;
210
211 str = va_arg(args, char*);
212 len = strlen(str) + 1;
e5e91eec 213 check_buf(this, len);
12ec91ba 214 memcpy(this->buf.ptr + this->buf.len, str, len);
e5e91eec
MW
215 this->buf.len += len;
216 break;
12ec91ba 217 }
b12c53ce 218 /* uint8_t */
8bcd9bd1 219 case HA_IKE_VERSION:
3e6736f6 220 case HA_INITIATOR:
d8748966
MW
221 case HA_IPSEC_MODE:
222 case HA_IPCOMP:
7999be5b 223 {
b12c53ce 224 uint8_t val;
7999be5b 225
34d240a6 226 val = va_arg(args, u_int);
7999be5b
MW
227 check_buf(this, sizeof(val));
228 this->buf.ptr[this->buf.len] = val;
229 this->buf.len += sizeof(val);
230 break;
231 }
b12c53ce 232 /* uint16_t */
f1e90883 233 case HA_ALG_DH:
d8748966
MW
234 case HA_ALG_PRF:
235 case HA_ALG_OLD_PRF:
236 case HA_ALG_ENCR:
237 case HA_ALG_ENCR_LEN:
238 case HA_ALG_INTEG:
239 case HA_INBOUND_CPI:
240 case HA_OUTBOUND_CPI:
241 case HA_SEGMENT:
98788537 242 case HA_ESN:
eed20c21 243 case HA_AUTH_METHOD:
765935c8 244 {
b12c53ce 245 uint16_t val;
765935c8 246
34d240a6 247 val = va_arg(args, u_int);
765935c8 248 check_buf(this, sizeof(val));
b12c53ce 249 *(uint16_t*)(this->buf.ptr + this->buf.len) = htons(val);
765935c8
MW
250 this->buf.len += sizeof(val);
251 break;
252 }
b12c53ce 253 /** uint32_t */
d8748966
MW
254 case HA_CONDITIONS:
255 case HA_EXTENSIONS:
256 case HA_INBOUND_SPI:
257 case HA_OUTBOUND_SPI:
ad2488fc 258 case HA_MID:
12ec91ba 259 {
b12c53ce 260 uint32_t val;
12ec91ba 261
34d240a6 262 val = va_arg(args, u_int);
12ec91ba 263 check_buf(this, sizeof(val));
b12c53ce 264 *(uint32_t*)(this->buf.ptr + this->buf.len) = htonl(val);
12ec91ba
MW
265 this->buf.len += sizeof(val);
266 break;
267 }
268 /** chunk_t */
d8748966
MW
269 case HA_NONCE_I:
270 case HA_NONCE_R:
271 case HA_SECRET:
8bcd9bd1
MW
272 case HA_LOCAL_DH:
273 case HA_REMOTE_DH:
274 case HA_PSK:
c8531b7e 275 case HA_IV:
d8748966 276 case HA_OLD_SKD:
12ec91ba
MW
277 {
278 chunk_t chunk;
279
280 chunk = va_arg(args, chunk_t);
b12c53ce
AS
281 check_buf(this, chunk.len + sizeof(uint16_t));
282 *(uint16_t*)(this->buf.ptr + this->buf.len) = htons(chunk.len);
283 memcpy(this->buf.ptr + this->buf.len + sizeof(uint16_t),
190edaf5 284 chunk.ptr, chunk.len);
b12c53ce 285 this->buf.len += chunk.len + sizeof(uint16_t);;
12ec91ba
MW
286 break;
287 }
7999be5b 288 /** traffic_selector_t */
d8748966
MW
289 case HA_LOCAL_TS:
290 case HA_REMOTE_TS:
7999be5b
MW
291 {
292 ts_encoding_t *enc;
293 traffic_selector_t *ts;
294 chunk_t data;
295
296 ts = va_arg(args, traffic_selector_t*);
297 data = chunk_cata("cc", ts->get_from_address(ts),
298 ts->get_to_address(ts));
299 check_buf(this, sizeof(ts_encoding_t) + data.len);
300 enc = (ts_encoding_t*)(this->buf.ptr + this->buf.len);
301 this->buf.len += sizeof(ts_encoding_t) + data.len;
302 enc->type = ts->get_type(ts);
303 enc->protocol = ts->get_protocol(ts);
304 enc->from_port = htons(ts->get_from_port(ts));
305 enc->to_port = htons(ts->get_to_port(ts));
306 enc->dynamic = ts->is_dynamic(ts);
307 memcpy(enc->encoding, data.ptr, data.len);
308 break;
309 }
e5e91eec 310 default:
12ec91ba 311 {
e5e91eec 312 DBG1(DBG_CFG, "unable to encode, attribute %d unknown", attribute);
b12c53ce 313 this->buf.len -= sizeof(uint8_t);
e5e91eec 314 break;
12ec91ba 315 }
e5e91eec 316 }
12ec91ba 317 va_end(args);
e5e91eec
MW
318}
319
190edaf5
MW
320/**
321 * Attribute enumerator implementation
322 */
323typedef struct {
89bd016e 324 /** implements enumerator_t */
190edaf5
MW
325 enumerator_t public;
326 /** position in message */
327 chunk_t buf;
328 /** cleanup handler of current element, if any */
329 void (*cleanup)(void* data);
330 /** data to pass to cleanup handler */
331 void *cleanup_data;
332} attribute_enumerator_t;
333
00c1bd06 334METHOD(enumerator_t, attribute_enumerate, bool,
95a63bf2 335 attribute_enumerator_t *this, va_list args)
190edaf5 336{
95a63bf2
TB
337 ha_message_attribute_t attr, *attr_out;
338 ha_message_value_t *value;
339
340 VA_ARGS_VGET(args, attr_out, value);
190edaf5
MW
341
342 if (this->cleanup)
343 {
344 this->cleanup(this->cleanup_data);
345 this->cleanup = NULL;
346 }
347 if (this->buf.len < 1)
348 {
349 return FALSE;
350 }
351 attr = this->buf.ptr[0];
352 this->buf = chunk_skip(this->buf, 1);
353 switch (attr)
354 {
355 /* ike_sa_id_t* */
d8748966
MW
356 case HA_IKE_ID:
357 case HA_IKE_REKEY_ID:
190edaf5
MW
358 {
359 ike_sa_id_encoding_t *enc;
360
361 if (this->buf.len < sizeof(ike_sa_id_encoding_t))
362 {
363 return FALSE;
364 }
365 enc = (ike_sa_id_encoding_t*)(this->buf.ptr);
1726795f
TB
366 value->ike_sa_id = ike_sa_id_create(enc->ike_version,
367 enc->initiator_spi, enc->responder_spi,
368 enc->initiator);
190edaf5
MW
369 *attr_out = attr;
370 this->cleanup = (void*)value->ike_sa_id->destroy;
371 this->cleanup_data = value->ike_sa_id;
372 this->buf = chunk_skip(this->buf, sizeof(ike_sa_id_encoding_t));
373 return TRUE;
374 }
375 /* identification_t* */
d8748966
MW
376 case HA_LOCAL_ID:
377 case HA_REMOTE_ID:
fa4f71c8 378 case HA_REMOTE_EAP_ID:
190edaf5
MW
379 {
380 identification_encoding_t *enc;
381
382 enc = (identification_encoding_t*)(this->buf.ptr);
383 if (this->buf.len < sizeof(identification_encoding_t) ||
384 this->buf.len < sizeof(identification_encoding_t) + enc->len)
385 {
386 return FALSE;
387 }
388 value->id = identification_create_from_encoding(enc->type,
389 chunk_create(enc->encoding, enc->len));
390 *attr_out = attr;
391 this->cleanup = (void*)value->id->destroy;
392 this->cleanup_data = value->id;
393 this->buf = chunk_skip(this->buf,
394 sizeof(identification_encoding_t) + enc->len);
395 return TRUE;
396 }
397 /* host_t* */
d8748966
MW
398 case HA_LOCAL_ADDR:
399 case HA_REMOTE_ADDR:
400 case HA_LOCAL_VIP:
401 case HA_REMOTE_VIP:
94bbc602 402 case HA_PEER_ADDR:
190edaf5
MW
403 {
404 host_encoding_t *enc;
405
406 enc = (host_encoding_t*)(this->buf.ptr);
407 if (this->buf.len < sizeof(host_encoding_t))
408 {
409 return FALSE;
410 }
411 value->host = host_create_from_chunk(enc->family,
412 chunk_create(enc->encoding,
413 this->buf.len - sizeof(host_encoding_t)),
414 ntohs(enc->port));
415 if (!value->host)
416 {
417 return FALSE;
418 }
419 *attr_out = attr;
420 this->cleanup = (void*)value->host->destroy;
421 this->cleanup_data = value->host;
422 this->buf = chunk_skip(this->buf, sizeof(host_encoding_t) +
423 value->host->get_address(value->host).len);
424 return TRUE;
425 }
426 /* char* */
d8748966 427 case HA_CONFIG_NAME:
190edaf5
MW
428 {
429 size_t len;
430
431 len = strnlen(this->buf.ptr, this->buf.len);
432 if (len >= this->buf.len)
433 {
434 return FALSE;
435 }
436 value->str = this->buf.ptr;
437 *attr_out = attr;
438 this->buf = chunk_skip(this->buf, len + 1);
439 return TRUE;
440 }
b12c53ce 441 /* uint8_t */
8bcd9bd1 442 case HA_IKE_VERSION:
3e6736f6 443 case HA_INITIATOR:
d8748966
MW
444 case HA_IPSEC_MODE:
445 case HA_IPCOMP:
7999be5b 446 {
b12c53ce 447 if (this->buf.len < sizeof(uint8_t))
7999be5b
MW
448 {
449 return FALSE;
450 }
b12c53ce 451 value->u8 = *(uint8_t*)this->buf.ptr;
7999be5b 452 *attr_out = attr;
b12c53ce 453 this->buf = chunk_skip(this->buf, sizeof(uint8_t));
7999be5b
MW
454 return TRUE;
455 }
b12c53ce 456 /** uint16_t */
f1e90883 457 case HA_ALG_DH:
d8748966
MW
458 case HA_ALG_PRF:
459 case HA_ALG_OLD_PRF:
460 case HA_ALG_ENCR:
461 case HA_ALG_ENCR_LEN:
462 case HA_ALG_INTEG:
463 case HA_INBOUND_CPI:
464 case HA_OUTBOUND_CPI:
465 case HA_SEGMENT:
98788537 466 case HA_ESN:
eed20c21 467 case HA_AUTH_METHOD:
765935c8 468 {
b12c53ce 469 if (this->buf.len < sizeof(uint16_t))
765935c8
MW
470 {
471 return FALSE;
472 }
b12c53ce 473 value->u16 = ntohs(*(uint16_t*)this->buf.ptr);
765935c8 474 *attr_out = attr;
b12c53ce 475 this->buf = chunk_skip(this->buf, sizeof(uint16_t));
765935c8
MW
476 return TRUE;
477 }
b12c53ce 478 /** uint32_t */
d8748966
MW
479 case HA_CONDITIONS:
480 case HA_EXTENSIONS:
481 case HA_INBOUND_SPI:
482 case HA_OUTBOUND_SPI:
ad2488fc 483 case HA_MID:
190edaf5 484 {
b12c53ce 485 if (this->buf.len < sizeof(uint32_t))
190edaf5
MW
486 {
487 return FALSE;
488 }
b12c53ce 489 value->u32 = ntohl(*(uint32_t*)this->buf.ptr);
190edaf5 490 *attr_out = attr;
b12c53ce 491 this->buf = chunk_skip(this->buf, sizeof(uint32_t));
190edaf5
MW
492 return TRUE;
493 }
494 /** chunk_t */
d8748966
MW
495 case HA_NONCE_I:
496 case HA_NONCE_R:
497 case HA_SECRET:
8bcd9bd1
MW
498 case HA_LOCAL_DH:
499 case HA_REMOTE_DH:
500 case HA_PSK:
c8531b7e 501 case HA_IV:
d8748966 502 case HA_OLD_SKD:
190edaf5
MW
503 {
504 size_t len;
505
b12c53ce 506 if (this->buf.len < sizeof(uint16_t))
190edaf5
MW
507 {
508 return FALSE;
509 }
b12c53ce
AS
510 len = ntohs(*(uint16_t*)this->buf.ptr);
511 this->buf = chunk_skip(this->buf, sizeof(uint16_t));
190edaf5
MW
512 if (this->buf.len < len)
513 {
514 return FALSE;
515 }
516 value->chunk.len = len;
517 value->chunk.ptr = this->buf.ptr;
518 *attr_out = attr;
519 this->buf = chunk_skip(this->buf, len);
520 return TRUE;
521 }
d8748966
MW
522 case HA_LOCAL_TS:
523 case HA_REMOTE_TS:
7999be5b
MW
524 {
525 ts_encoding_t *enc;
526 host_t *host;
527 int addr_len;
528
529 enc = (ts_encoding_t*)(this->buf.ptr);
530 if (this->buf.len < sizeof(ts_encoding_t))
531 {
532 return FALSE;
533 }
534 switch (enc->type)
535 {
536 case TS_IPV4_ADDR_RANGE:
537 addr_len = 4;
538 if (this->buf.len < sizeof(ts_encoding_t) + 2 * addr_len)
539 {
540 return FALSE;
541 }
542 break;
543 case TS_IPV6_ADDR_RANGE:
544 addr_len = 16;
545 if (this->buf.len < sizeof(ts_encoding_t) + 2 * addr_len)
546 {
547 return FALSE;
548 }
549 break;
550 default:
551 return FALSE;
552 }
553 if (enc->dynamic)
554 {
555 host = host_create_from_chunk(0,
556 chunk_create(enc->encoding, addr_len), 0);
557 if (!host)
558 {
559 return FALSE;
560 }
561 value->ts = traffic_selector_create_dynamic(enc->protocol,
562 ntohs(enc->from_port), ntohs(enc->to_port));
563 value->ts->set_address(value->ts, host);
564 host->destroy(host);
565 }
566 else
567 {
568 value->ts = traffic_selector_create_from_bytes(enc->protocol,
569 enc->type, chunk_create(enc->encoding, addr_len),
570 ntohs(enc->from_port),
571 chunk_create(enc->encoding + addr_len, addr_len),
572 ntohs(enc->to_port));
573 if (!value->ts)
574 {
575 return FALSE;
576 }
577 }
578 *attr_out = attr;
579 this->cleanup = (void*)value->ts->destroy;
580 this->cleanup_data = value->ts;
581 this->buf = chunk_skip(this->buf, sizeof(ts_encoding_t)
582 + addr_len * 2);
583 return TRUE;
584 }
190edaf5
MW
585 default:
586 {
587 return FALSE;
588 }
589 }
590}
591
00c1bd06
MW
592METHOD(enumerator_t, enum_destroy, void,
593 attribute_enumerator_t *this)
190edaf5
MW
594{
595 if (this->cleanup)
596 {
597 this->cleanup(this->cleanup_data);
598 }
599 free(this);
600}
601
00c1bd06
MW
602METHOD(ha_message_t, create_attribute_enumerator, enumerator_t*,
603 private_ha_message_t *this)
e5e91eec 604{
00c1bd06 605 attribute_enumerator_t *e;
190edaf5 606
00c1bd06
MW
607 INIT(e,
608 .public = {
95a63bf2
TB
609 .enumerate = enumerator_enumerate_default,
610 .venumerate = _attribute_enumerate,
00c1bd06
MW
611 .destroy = _enum_destroy,
612 },
613 .buf = chunk_skip(this->buf, 2),
614 );
190edaf5
MW
615
616 return &e->public;
e5e91eec
MW
617}
618
00c1bd06
MW
619METHOD(ha_message_t, get_encoding, chunk_t,
620 private_ha_message_t *this)
e5e91eec
MW
621{
622 return this->buf;
623}
624
00c1bd06
MW
625METHOD(ha_message_t, destroy, void,
626 private_ha_message_t *this)
e5e91eec
MW
627{
628 free(this->buf.ptr);
629 free(this);
630}
631
632
d8748966 633static private_ha_message_t *ha_message_create_generic()
e5e91eec 634{
00c1bd06 635 private_ha_message_t *this;
e5e91eec 636
00c1bd06
MW
637 INIT(this,
638 .public = {
639 .get_type = _get_type,
640 .add_attribute = _add_attribute,
641 .create_attribute_enumerator = _create_attribute_enumerator,
642 .get_encoding = _get_encoding,
643 .destroy = _destroy,
644 },
645 );
e5e91eec
MW
646 return this;
647}
648
649/**
650 * See header
651 */
d8748966 652ha_message_t *ha_message_create(ha_message_type_t type)
e5e91eec 653{
d8748966 654 private_ha_message_t *this = ha_message_create_generic();
e5e91eec 655
12ec91ba 656 this->allocated = ALLOCATION_BLOCK;
e5e91eec
MW
657 this->buf.ptr = malloc(this->allocated);
658 this->buf.len = 2;
d8748966 659 this->buf.ptr[0] = HA_MESSAGE_VERSION;
e5e91eec
MW
660 this->buf.ptr[1] = type;
661
662 return &this->public;
663}
664
665/**
666 * See header
667 */
d8748966 668ha_message_t *ha_message_parse(chunk_t data)
e5e91eec 669{
d8748966 670 private_ha_message_t *this;
e5e91eec
MW
671
672 if (data.len < 2)
673 {
d8748966 674 DBG1(DBG_CFG, "HA message too short");
e5e91eec
MW
675 return NULL;
676 }
d8748966 677 if (data.ptr[0] != HA_MESSAGE_VERSION)
e5e91eec 678 {
d8748966
MW
679 DBG1(DBG_CFG, "HA message has version %d, expected %d",
680 data.ptr[0], HA_MESSAGE_VERSION);
e5e91eec
MW
681 return NULL;
682 }
683
d8748966 684 this = ha_message_create_generic();
e5e91eec
MW
685 this->buf = chunk_clone(data);
686 this->allocated = this->buf.len;
687
688 return &this->public;
689}
690