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