added ERX_SUPPORTED IKEv2 Notify
[strongswan.git] / src / libcharon / encoding / payloads / notify_payload.c
1 /*
2 * Copyright (C) 2005-2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 * Copyright (C) 2006-2008 Tobias Brunner
5 * Copyright (C) 2006 Daniel Roethlisberger
6 * Copyright (C) 2005 Jan Hutter
7 * Hochschule fuer Technik Rapperswil
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 * for more details.
18 */
19
20 #include <stddef.h>
21
22 #include "notify_payload.h"
23
24 #include <daemon.h>
25 #include <encoding/payloads/encodings.h>
26 #include <crypto/hashers/hasher.h>
27
28 ENUM_BEGIN(notify_type_names, UNSUPPORTED_CRITICAL_PAYLOAD, UNSUPPORTED_CRITICAL_PAYLOAD,
29 "UNSUPPORTED_CRITICAL_PAYLOAD");
30 ENUM_NEXT(notify_type_names, INVALID_IKE_SPI, INVALID_MAJOR_VERSION, UNSUPPORTED_CRITICAL_PAYLOAD,
31 "INVALID_IKE_SPI",
32 "INVALID_MAJOR_VERSION");
33 ENUM_NEXT(notify_type_names, INVALID_SYNTAX, INVALID_SYNTAX, INVALID_MAJOR_VERSION,
34 "INVALID_SYNTAX");
35 ENUM_NEXT(notify_type_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVALID_SYNTAX,
36 "INVALID_MESSAGE_ID");
37 ENUM_NEXT(notify_type_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID,
38 "INVALID_SPI");
39 ENUM_NEXT(notify_type_names, ATTRIBUTES_NOT_SUPPORTED, NO_PROPOSAL_CHOSEN, INVALID_SPI,
40 "ATTRIBUTES_NOT_SUPPORTED",
41 "NO_PROPOSAL_CHOSEN");
42 ENUM_NEXT(notify_type_names, PAYLOAD_MALFORMED, AUTHENTICATION_FAILED, NO_PROPOSAL_CHOSEN,
43 "PAYLOAD_MALFORMED",
44 "INVALID_KE_PAYLOAD",
45 "INVALID_ID_INFORMATION",
46 "INVALID_CERT_ENCODING",
47 "INVALID_CERTIFICATE",
48 "CERT_TYPE_UNSUPPORTED",
49 "INVALID_CERT_AUTHORITY",
50 "INVALID_HASH_INFORMATION",
51 "AUTHENTICATION_FAILED");
52 ENUM_NEXT(notify_type_names, SINGLE_PAIR_REQUIRED, CHILD_SA_NOT_FOUND, AUTHENTICATION_FAILED,
53 "SINGLE_PAIR_REQUIRED",
54 "NO_ADDITIONAL_SAS",
55 "INTERNAL_ADDRESS_FAILURE",
56 "FAILED_CP_REQUIRED",
57 "TS_UNACCEPTABLE",
58 "INVALID_SELECTORS",
59 "UNACCEPTABLE_ADDRESSES",
60 "UNEXPECTED_NAT_DETECTED",
61 "USE_ASSIGNED_HoA",
62 "TEMPORARY_FAILURE",
63 "CHILD_SA_NOT_FOUND");
64 ENUM_NEXT(notify_type_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, CHILD_SA_NOT_FOUND,
65 "ME_CONNECT_FAILED");
66 ENUM_NEXT(notify_type_names, MS_NOTIFY_STATUS, MS_NOTIFY_STATUS, ME_CONNECT_FAILED,
67 "MS_NOTIFY_STATUS");
68 ENUM_NEXT(notify_type_names, INITIAL_CONTACT, ERX_SUPPORTED, MS_NOTIFY_STATUS,
69 "INITIAL_CONTACT",
70 "SET_WINDOW_SIZE",
71 "ADDITIONAL_TS_POSSIBLE",
72 "IPCOMP_SUPPORTED",
73 "NAT_DETECTION_SOURCE_IP",
74 "NAT_DETECTION_DESTINATION_IP",
75 "COOKIE",
76 "USE_TRANSPORT_MODE",
77 "HTTP_CERT_LOOKUP_SUPPORTED",
78 "REKEY_SA",
79 "ESP_TFC_PADDING_NOT_SUPPORTED",
80 "NON_FIRST_FRAGMENTS_ALSO",
81 "MOBIKE_SUPPORTED",
82 "ADDITIONAL_IP4_ADDRESS",
83 "ADDITIONAL_IP6_ADDRESS",
84 "NO_ADDITIONAL_ADDRESSES",
85 "UPDATE_SA_ADDRESSES",
86 "COOKIE2",
87 "NO_NATS_ALLOWED",
88 "AUTH_LIFETIME",
89 "MULTIPLE_AUTH_SUPPORTED",
90 "ANOTHER_AUTH_FOLLOWS",
91 "REDIRECT_SUPPORTED",
92 "REDIRECT",
93 "REDIRECTED_FROM",
94 "TICKET_LT_OPAQUE",
95 "TICKET_REQUEST",
96 "TICKET_ACK",
97 "TICKET_NACK",
98 "TICKET_OPAQUE",
99 "LINK_ID",
100 "USE_WESP_MODE",
101 "ROHC_SUPPORTED",
102 "EAP_ONLY_AUTHENTICATION",
103 "CHILDLESS_IKEV2_SUPPORTED",
104 "QUICK_CRASH_DETECTION",
105 "IKEV2_MESSAGE_ID_SYNC_SUPPORTED",
106 "IKEV2_REPLAY_COUNTER_SYNC_SUPPORTED",
107 "IKEV2_MESSAGE_ID_SYNC",
108 "IPSEC_REPLAY_COUNTER_SYNC",
109 "SECURE PASSWORD_METHOD",
110 "PSK_PERSIST",
111 "PSK_CONFIRM",
112 "ERX_SUPPORTED");
113 ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, ERX_SUPPORTED,
114 "INITIAL_CONTACT");
115 ENUM_NEXT(notify_type_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
116 "DPD_R_U_THERE",
117 "DPD_R_U_THERE_ACK");
118 ENUM_NEXT(notify_type_names, UNITY_LOAD_BALANCE, UNITY_LOAD_BALANCE, DPD_R_U_THERE_ACK,
119 "UNITY_LOAD_BALANCE");
120 ENUM_NEXT(notify_type_names, USE_BEET_MODE, USE_BEET_MODE, UNITY_LOAD_BALANCE,
121 "USE_BEET_MODE");
122 ENUM_NEXT(notify_type_names, ME_MEDIATION, RADIUS_ATTRIBUTE, USE_BEET_MODE,
123 "ME_MEDIATION",
124 "ME_ENDPOINT",
125 "ME_CALLBACK",
126 "ME_CONNECTID",
127 "ME_CONNECTKEY",
128 "ME_CONNECTAUTH",
129 "ME_RESPONSE",
130 "RADIUS_ATTRIBUTE",);
131 ENUM_END(notify_type_names, RADIUS_ATTRIBUTE);
132
133
134 ENUM_BEGIN(notify_type_short_names, UNSUPPORTED_CRITICAL_PAYLOAD, UNSUPPORTED_CRITICAL_PAYLOAD,
135 "CRIT");
136 ENUM_NEXT(notify_type_short_names, INVALID_IKE_SPI, INVALID_MAJOR_VERSION, UNSUPPORTED_CRITICAL_PAYLOAD,
137 "INVAL_IKE_SPI",
138 "INVAL_MAJOR");
139 ENUM_NEXT(notify_type_short_names, INVALID_SYNTAX, INVALID_SYNTAX, INVALID_MAJOR_VERSION,
140 "INVAL_SYN");
141 ENUM_NEXT(notify_type_short_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVALID_SYNTAX,
142 "INVAL_MID");
143 ENUM_NEXT(notify_type_short_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID,
144 "INVAL_SPI");
145 ENUM_NEXT(notify_type_short_names, ATTRIBUTES_NOT_SUPPORTED, NO_PROPOSAL_CHOSEN, INVALID_SPI,
146 "ATTR_UNSUP",
147 "NO_PROP");
148 ENUM_NEXT(notify_type_short_names, PAYLOAD_MALFORMED, AUTHENTICATION_FAILED, NO_PROPOSAL_CHOSEN,
149 "PLD_MAL",
150 "INVAL_KE",
151 "INVAL_ID",
152 "INVAL_CERTEN",
153 "INVAL_CERT",
154 "CERT_UNSUP",
155 "INVAL_CA",
156 "INVAL_HASH",
157 "AUTH_FAILED");
158 ENUM_NEXT(notify_type_short_names, SINGLE_PAIR_REQUIRED, CHILD_SA_NOT_FOUND, AUTHENTICATION_FAILED,
159 "SINGLE_PAIR",
160 "NO_ADD_SAS",
161 "INT_ADDR_FAIL",
162 "FAIL_CP_REQ",
163 "TS_UNACCEPT",
164 "INVAL_SEL",
165 "UNACCEPT_ADDR",
166 "UNEXPECT_NAT",
167 "ASSIGNED_HoA",
168 "TEMP_FAIL",
169 "NO_CHILD_SA");
170 ENUM_NEXT(notify_type_short_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, CHILD_SA_NOT_FOUND,
171 "ME_CONN_FAIL");
172 ENUM_NEXT(notify_type_short_names, MS_NOTIFY_STATUS, MS_NOTIFY_STATUS, ME_CONNECT_FAILED,
173 "MS_STATUS");
174 ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, ERX_SUPPORTED, MS_NOTIFY_STATUS,
175 "INIT_CONTACT",
176 "SET_WINSIZE",
177 "ADD_TS_POSS",
178 "IPCOMP_SUP",
179 "NATD_S_IP",
180 "NATD_D_IP",
181 "COOKIE",
182 "USE_TRANSP",
183 "HTTP_CERT_LOOK",
184 "REKEY_SA",
185 "ESP_TFC_PAD_N",
186 "NON_FIRST_FRAG",
187 "MOBIKE_SUP",
188 "ADD_4_ADDR",
189 "ADD_6_ADDR",
190 "NO_ADD_ADDR",
191 "UPD_SA_ADDR",
192 "COOKIE2",
193 "NO_NATS",
194 "AUTH_LFT",
195 "MULT_AUTH",
196 "AUTH_FOLLOWS",
197 "REDIR_SUP",
198 "REDIR",
199 "REDIR_FROM",
200 "TKT_LT_OPAK",
201 "TKT_REQ",
202 "TKT_ACK",
203 "TKT_NACK",
204 "TKT_OPAK",
205 "LINK_ID",
206 "WESP_MODE",
207 "ROHC_SUP",
208 "EAP_ONLY",
209 "CHDLESS_SUP",
210 "CRASH_DET",
211 "MSG_ID_SYN_SUP",
212 "RPL_CTR_SYN_SUP",
213 "MSG_ID_SYN",
214 "RPL_CTR_SYN",
215 "SEC_PASSWD",
216 "PSK_PST",
217 "PSK_CFM",
218 "ERX_SUP");
219 ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, ERX_SUPPORTED,
220 "INITIAL_CONTACT");
221 ENUM_NEXT(notify_type_short_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1,
222 "DPD",
223 "DPD_ACK");
224 ENUM_NEXT(notify_type_short_names, UNITY_LOAD_BALANCE, UNITY_LOAD_BALANCE, DPD_R_U_THERE_ACK,
225 "UNITY_LB");
226 ENUM_NEXT(notify_type_short_names, USE_BEET_MODE, USE_BEET_MODE, UNITY_LOAD_BALANCE,
227 "BEET_MODE");
228 ENUM_NEXT(notify_type_short_names, ME_MEDIATION, RADIUS_ATTRIBUTE, USE_BEET_MODE,
229 "ME_MED",
230 "ME_EP",
231 "ME_CB",
232 "ME_CID",
233 "ME_CKEY",
234 "ME_CAUTH",
235 "ME_R",
236 "RADIUS");
237 ENUM_END(notify_type_short_names, RADIUS_ATTRIBUTE);
238
239
240 typedef struct private_notify_payload_t private_notify_payload_t;
241
242 /**
243 * Private data of an notify_payload_t object.
244 */
245 struct private_notify_payload_t {
246
247 /**
248 * Public notify_payload_t interface.
249 */
250 notify_payload_t public;
251
252 /**
253 * Next payload type.
254 */
255 u_int8_t next_payload;
256
257 /**
258 * Critical flag.
259 */
260 bool critical;
261
262 /**
263 * reserved bits
264 */
265 bool reserved[8];
266
267 /**
268 * Length of this payload.
269 */
270 u_int16_t payload_length;
271
272 /**
273 * Domain of interpretation, IKEv1 only.
274 */
275 u_int32_t doi;
276
277 /**
278 * Protocol id.
279 */
280 u_int8_t protocol_id;
281
282 /**
283 * Spi size.
284 */
285 u_int8_t spi_size;
286
287 /**
288 * Notify message type.
289 */
290 u_int16_t notify_type;
291
292 /**
293 * Security parameter index (spi).
294 */
295 chunk_t spi;
296
297 /**
298 * Notification data.
299 */
300 chunk_t notify_data;
301
302 /**
303 * Type of payload, NOTIFY or NOTIFY_V1
304 */
305 payload_type_t type;
306 };
307
308 /**
309 * Encoding rules for an IKEv2 notification payload
310 */
311 static encoding_rule_t encodings_v2[] = {
312 /* 1 Byte next payload type, stored in the field next_payload */
313 { U_INT_8, offsetof(private_notify_payload_t, next_payload) },
314 /* the critical bit */
315 { FLAG, offsetof(private_notify_payload_t, critical) },
316 /* 7 Bit reserved bits, nowhere stored */
317 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[0]) },
318 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[1]) },
319 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[2]) },
320 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[3]) },
321 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[4]) },
322 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[5]) },
323 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[6]) },
324 /* Length of the whole payload*/
325 { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
326 /* Protocol ID as 8 bit field*/
327 { U_INT_8, offsetof(private_notify_payload_t, protocol_id) },
328 /* SPI Size as 8 bit field*/
329 { SPI_SIZE, offsetof(private_notify_payload_t, spi_size) },
330 /* Notify message type as 16 bit field*/
331 { U_INT_16, offsetof(private_notify_payload_t, notify_type) },
332 /* SPI as variable length field*/
333 { SPI, offsetof(private_notify_payload_t, spi) },
334 /* Key Exchange Data is from variable size */
335 { CHUNK_DATA, offsetof(private_notify_payload_t, notify_data) },
336 };
337
338 /*
339 1 2 3
340 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
341 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
342 ! Next Payload !C! RESERVED ! Payload Length !
343 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
344 ! Protocol ID ! SPI Size ! Notify Message Type !
345 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
346 ! !
347 ~ Security Parameter Index (SPI) ~
348 ! !
349 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
350 ! !
351 ~ Notification Data ~
352 ! !
353 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
354 */
355 /**
356 * Encoding rules for an IKEv1 notification payload
357 */
358 static encoding_rule_t encodings_v1[] = {
359 /* 1 Byte next payload type, stored in the field next_payload */
360 { U_INT_8, offsetof(private_notify_payload_t, next_payload) },
361 /* 8 reserved bits */
362 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[0]) },
363 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[1]) },
364 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[2]) },
365 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[3]) },
366 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[4]) },
367 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[5]) },
368 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[6]) },
369 { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[7]) },
370 /* Length of the whole payload*/
371 { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) },
372 /* DOI as 32 bit field*/
373 { U_INT_32, offsetof(private_notify_payload_t, doi) },
374 /* Protocol ID as 8 bit field*/
375 { U_INT_8, offsetof(private_notify_payload_t, protocol_id) },
376 /* SPI Size as 8 bit field*/
377 { SPI_SIZE, offsetof(private_notify_payload_t, spi_size) },
378 /* Notify message type as 16 bit field*/
379 { U_INT_16, offsetof(private_notify_payload_t, notify_type) },
380 /* SPI as variable length field*/
381 { SPI, offsetof(private_notify_payload_t, spi) },
382 /* Key Exchange Data is from variable size */
383 { CHUNK_DATA, offsetof(private_notify_payload_t, notify_data) },
384 };
385
386 /*
387 1 2 3
388 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
389 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
390 ! Next Payload ! RESERVED ! Payload Length !
391 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
392 ! DOI !
393 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
394 ! Protocol ID ! SPI Size ! Notify Message Type !
395 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
396 ! !
397 ~ Security Parameter Index (SPI) ~
398 ! !
399 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
400 ! !
401 ~ Notification Data ~
402 ! !
403 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
404 */
405
406
407 METHOD(payload_t, verify, status_t,
408 private_notify_payload_t *this)
409 {
410 bool bad_length = FALSE;
411
412 switch (this->protocol_id)
413 {
414 case PROTO_NONE:
415 case PROTO_IKE:
416 case PROTO_AH:
417 case PROTO_ESP:
418 break;
419 default:
420 DBG1(DBG_ENC, "Unknown protocol (%d)", this->protocol_id);
421 return FAILED;
422 }
423
424 switch (this->notify_type)
425 {
426 case INVALID_KE_PAYLOAD:
427 {
428 if (this->type == NOTIFY && this->notify_data.len != 2)
429 {
430 bad_length = TRUE;
431 }
432 break;
433 }
434 case NAT_DETECTION_SOURCE_IP:
435 case NAT_DETECTION_DESTINATION_IP:
436 case ME_CONNECTAUTH:
437 {
438 if (this->notify_data.len != HASH_SIZE_SHA1)
439 {
440 bad_length = TRUE;
441 }
442 break;
443 }
444 case INVALID_SYNTAX:
445 case INVALID_MAJOR_VERSION:
446 case NO_PROPOSAL_CHOSEN:
447 {
448 if (this->type == NOTIFY && this->notify_data.len != 0)
449 {
450 bad_length = TRUE;
451 }
452 break;
453 }
454 case ADDITIONAL_IP4_ADDRESS:
455 {
456 if (this->notify_data.len != 4)
457 {
458 bad_length = TRUE;
459 }
460 break;
461 }
462 case ADDITIONAL_IP6_ADDRESS:
463 {
464 if (this->notify_data.len != 16)
465 {
466 bad_length = TRUE;
467 }
468 break;
469 }
470 case AUTH_LIFETIME:
471 {
472 if (this->notify_data.len != 4)
473 {
474 bad_length = TRUE;
475 }
476 break;
477 }
478 case IPCOMP_SUPPORTED:
479 {
480 if (this->notify_data.len != 3)
481 {
482 bad_length = TRUE;
483 }
484 break;
485 }
486 case ME_ENDPOINT:
487 if (this->notify_data.len != 8 &&
488 this->notify_data.len != 12 &&
489 this->notify_data.len != 24)
490 {
491 bad_length = TRUE;
492 }
493 break;
494 case ME_CONNECTID:
495 if (this->notify_data.len < 4 ||
496 this->notify_data.len > 16)
497 {
498 bad_length = TRUE;
499 }
500 break;
501 case ME_CONNECTKEY:
502 if (this->notify_data.len < 16 ||
503 this->notify_data.len > 32)
504 {
505 bad_length = TRUE;
506 }
507 break;
508 case DPD_R_U_THERE:
509 case DPD_R_U_THERE_ACK:
510 if (this->notify_data.len != 4)
511 {
512 bad_length = TRUE;
513 }
514 break;
515 default:
516 /* TODO: verify */
517 break;
518 }
519 if (bad_length)
520 {
521 DBG1(DBG_ENC, "invalid notify data length for %N (%d)",
522 notify_type_names, this->notify_type,
523 this->notify_data.len);
524 return FAILED;
525 }
526 return SUCCESS;
527 }
528
529 METHOD(payload_t, get_encoding_rules, int,
530 private_notify_payload_t *this, encoding_rule_t **rules)
531 {
532 if (this->type == NOTIFY)
533 {
534 *rules = encodings_v2;
535 return countof(encodings_v2);
536 }
537 *rules = encodings_v1;
538 return countof(encodings_v1);
539 }
540
541 METHOD(payload_t, get_header_length, int,
542 private_notify_payload_t *this)
543 {
544 if (this->type == NOTIFY)
545 {
546 return 8 + this->spi_size;
547 }
548 return 12 + this->spi_size;
549 }
550
551 METHOD(payload_t, get_type, payload_type_t,
552 private_notify_payload_t *this)
553 {
554 return this->type;
555 }
556
557 METHOD(payload_t, get_next_type, payload_type_t,
558 private_notify_payload_t *this)
559 {
560 return this->next_payload;
561 }
562
563 METHOD(payload_t, set_next_type, void,
564 private_notify_payload_t *this, payload_type_t type)
565 {
566 this->next_payload = type;
567 }
568
569 /**
570 * recompute the payloads length.
571 */
572 static void compute_length(private_notify_payload_t *this)
573 {
574 this->payload_length = get_header_length(this) + this->notify_data.len;
575 }
576
577 METHOD(payload_t, get_length, size_t,
578 private_notify_payload_t *this)
579 {
580 return this->payload_length;
581 }
582
583 METHOD(notify_payload_t, get_protocol_id, u_int8_t,
584 private_notify_payload_t *this)
585 {
586 return this->protocol_id;
587 }
588
589 METHOD(notify_payload_t, set_protocol_id, void,
590 private_notify_payload_t *this, u_int8_t protocol_id)
591 {
592 this->protocol_id = protocol_id;
593 }
594
595 METHOD(notify_payload_t, get_notify_type, notify_type_t,
596 private_notify_payload_t *this)
597 {
598 return this->notify_type;
599 }
600
601 METHOD(notify_payload_t, set_notify_type, void,
602 private_notify_payload_t *this, notify_type_t notify_type)
603 {
604 this->notify_type = notify_type;
605 }
606
607 METHOD(notify_payload_t, get_spi, u_int32_t,
608 private_notify_payload_t *this)
609 {
610 switch (this->protocol_id)
611 {
612 case PROTO_AH:
613 case PROTO_ESP:
614 if (this->spi.len == 4)
615 {
616 return *((u_int32_t*)this->spi.ptr);
617 }
618 default:
619 break;
620 }
621 return 0;
622 }
623
624 METHOD(notify_payload_t, set_spi, void,
625 private_notify_payload_t *this, u_int32_t spi)
626 {
627 chunk_free(&this->spi);
628 switch (this->protocol_id)
629 {
630 case PROTO_AH:
631 case PROTO_ESP:
632 this->spi = chunk_alloc(4);
633 *((u_int32_t*)this->spi.ptr) = spi;
634 break;
635 default:
636 break;
637 }
638 this->spi_size = this->spi.len;
639 compute_length(this);
640 }
641
642 METHOD(notify_payload_t, get_spi_data, chunk_t,
643 private_notify_payload_t *this)
644 {
645 switch (this->protocol_id)
646 {
647 case PROTO_IKE:
648 if (this->spi.len == 16)
649 {
650 return this->spi;
651 }
652 default:
653 break;
654 }
655 return chunk_empty;
656 }
657
658 METHOD(notify_payload_t, set_spi_data, void,
659 private_notify_payload_t *this, chunk_t spi)
660 {
661 chunk_free(&this->spi);
662 switch (this->protocol_id)
663 {
664 case PROTO_IKE:
665 this->spi = chunk_clone(spi);
666 default:
667 break;
668 }
669 this->spi_size = this->spi.len;
670 compute_length(this);
671 }
672
673 METHOD(notify_payload_t, get_notification_data, chunk_t,
674 private_notify_payload_t *this)
675 {
676 return this->notify_data;
677 }
678
679 METHOD(notify_payload_t, set_notification_data, void,
680 private_notify_payload_t *this, chunk_t data)
681 {
682 free(this->notify_data.ptr);
683 this->notify_data = chunk_clone(data);
684 compute_length(this);
685 }
686
687 METHOD2(payload_t, notify_payload_t, destroy, void,
688 private_notify_payload_t *this)
689 {
690 free(this->notify_data.ptr);
691 free(this->spi.ptr);
692 free(this);
693 }
694
695 /*
696 * Described in header
697 */
698 notify_payload_t *notify_payload_create(payload_type_t type)
699 {
700 private_notify_payload_t *this;
701
702 INIT(this,
703 .public = {
704 .payload_interface = {
705 .verify = _verify,
706 .get_encoding_rules = _get_encoding_rules,
707 .get_header_length = _get_header_length,
708 .get_length = _get_length,
709 .get_next_type = _get_next_type,
710 .set_next_type = _set_next_type,
711 .get_type = _get_type,
712 .destroy = _destroy,
713 },
714 .get_protocol_id = _get_protocol_id,
715 .set_protocol_id = _set_protocol_id,
716 .get_notify_type = _get_notify_type,
717 .set_notify_type = _set_notify_type,
718 .get_spi = _get_spi,
719 .set_spi = _set_spi,
720 .get_spi_data = _get_spi_data,
721 .set_spi_data = _set_spi_data,
722 .get_notification_data = _get_notification_data,
723 .set_notification_data = _set_notification_data,
724 .destroy = _destroy,
725 },
726 .doi = IKEV1_DOI_IPSEC,
727 .next_payload = NO_PAYLOAD,
728 .type = type,
729 );
730 compute_length(this);
731 return &this->public;
732 }
733
734 /*
735 * Described in header.
736 */
737 notify_payload_t *notify_payload_create_from_protocol_and_type(
738 payload_type_t type, protocol_id_t protocol, notify_type_t notify)
739 {
740 notify_payload_t *this = notify_payload_create(type);
741
742 this->set_notify_type(this, notify);
743 this->set_protocol_id(this, protocol);
744
745 return this;
746 }