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