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