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