ce3a3fd00a33dc7913ae81f672cacb0772d6891d
[strongswan.git] / src / charon / sa / tasks / ike_p2p.c
1 /*
2 * Copyright (C) 2007 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * $Id$
16 */
17
18 #include "ike_p2p.h"
19
20 #include <string.h>
21
22 #include <daemon.h>
23 #include <config/peer_cfg.h>
24 #include <encoding/payloads/id_payload.h>
25 #include <encoding/payloads/notify_payload.h>
26 #include <encoding/payloads/endpoint_notify.h>
27 #include <processing/jobs/mediation_job.h>
28
29 #define P2P_SESSIONID_LEN 8
30 #define P2P_SESSIONKEY_LEN 16
31
32 /* FIXME: proposed values */
33 #define P2P_SESSIONID_MIN_LEN 4
34 #define P2P_SESSIONID_MAX_LEN 16
35 #define P2P_SESSIONKEY_MIN_LEN 8
36 #define P2P_SESSIONKEY_MAX_LEN 64
37
38
39 typedef struct private_ike_p2p_t private_ike_p2p_t;
40
41 /**
42 * Private members of a ike_p2p_t task.
43 */
44 struct private_ike_p2p_t {
45
46 /**
47 * Public methods and task_t interface.
48 */
49 ike_p2p_t public;
50
51 /**
52 * Assigned IKE_SA.
53 */
54 ike_sa_t *ike_sa;
55
56 /**
57 * Are we the initiator?
58 */
59 bool initiator;
60
61 /**
62 * Is this a mediation connection?
63 */
64 bool mediation;
65
66 /**
67 * Is this the response from another peer?
68 */
69 bool response;
70
71 /**
72 * Gathered endpoints
73 */
74 linked_list_t *local_endpoints;
75
76 /**
77 * Parsed endpoints
78 */
79 linked_list_t *remote_endpoints;
80
81 /**
82 * Did the peer request a callback?
83 */
84 bool callback;
85
86 /**
87 * Did the connect fail?
88 */
89 bool failed;
90
91 /**
92 * Was there anything wrong with the payloads?
93 */
94 bool invalid_syntax;
95
96 /**
97 * The requested peer
98 */
99 identification_t *peer_id;
100 /**
101 * Received ID used for connectivity checks
102 */
103 chunk_t session_id;
104
105 /**
106 * Received key used for connectivity checks
107 */
108 chunk_t session_key;
109
110 /**
111 * Peer config of the mediated connection
112 */
113 peer_cfg_t *mediated_cfg;
114
115 };
116
117 /**
118 * Adds a list of endpoints as notifies to a given message
119 */
120 static void add_endpoints_to_message(message_t *message, linked_list_t *endpoints)
121 {
122 iterator_t *iterator;
123 endpoint_notify_t *endpoint;
124
125 iterator = endpoints->create_iterator(endpoints, TRUE);
126 while (iterator->iterate(iterator, (void**)&endpoint))
127 {
128 message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
129 }
130 iterator->destroy(iterator);
131 }
132
133 /**
134 * Gathers endpoints and adds them to the current message
135 */
136 static void gather_and_add_endpoints(private_ike_p2p_t *this, message_t *message)
137 {
138 iterator_t *iterator;
139 host_t *addr, *host;
140 u_int16_t port;
141
142 /* get the port that is used to communicate with the ms */
143 host = this->ike_sa->get_my_host(this->ike_sa);
144 port = host->get_port(host);
145
146 iterator = charon->kernel_interface->create_address_iterator(
147 charon->kernel_interface);
148 while (iterator->iterate(iterator, (void**)&addr))
149 {
150 host = addr->clone(addr);
151 host->set_port(host, port);
152
153 this->local_endpoints->insert_last(this->local_endpoints,
154 endpoint_notify_create_from_host(HOST, host, NULL));
155
156 host->destroy(host);
157 }
158 iterator->destroy(iterator);
159
160 host = this->ike_sa->get_server_reflexive_host(this->ike_sa);
161 if (host)
162 {
163 this->local_endpoints->insert_last(this->local_endpoints,
164 endpoint_notify_create_from_host(SERVER_REFLEXIVE, host,
165 this->ike_sa->get_my_host(this->ike_sa)));
166 }
167
168 add_endpoints_to_message(message, this->local_endpoints);
169 }
170
171 /**
172 * read notifys from message and evaluate them
173 */
174 static void process_payloads(private_ike_p2p_t *this, message_t *message)
175 {
176 iterator_t *iterator;
177 payload_t *payload;
178
179 iterator = message->get_payload_iterator(message);
180 while (iterator->iterate(iterator, (void**)&payload))
181 {
182 if (payload->get_type(payload) != NOTIFY)
183 {
184 continue;
185 }
186
187 notify_payload_t *notify = (notify_payload_t*)payload;
188
189 switch (notify->get_notify_type(notify))
190 {
191 case P2P_CONNECT_FAILED:
192 {
193 DBG2(DBG_IKE, "received P2P_CONNECT_FAILED notify");
194 this->failed = TRUE;
195 break;
196 }
197 case P2P_MEDIATION:
198 {
199 DBG2(DBG_IKE, "received P2P_MEDIATION notify");
200 this->mediation = TRUE;
201 break;
202 }
203 case P2P_ENDPOINT:
204 {
205 endpoint_notify_t *endpoint = endpoint_notify_create_from_payload(notify);
206 if (!endpoint)
207 {
208 DBG1(DBG_IKE, "received invalid P2P_ENDPOINT notify");
209 break;
210 }
211 DBG1(DBG_IKE, "received %N P2P_ENDPOINT %#H", p2p_endpoint_type_names,
212 endpoint->get_type(endpoint), endpoint->get_host(endpoint));
213
214 this->remote_endpoints->insert_last(this->remote_endpoints, endpoint);
215 break;
216 }
217 case P2P_CALLBACK:
218 {
219 DBG2(DBG_IKE, "received P2P_CALLBACK notify");
220 this->callback = TRUE;
221 break;
222 }
223 case P2P_SESSIONID:
224 {
225 chunk_free(&this->session_id);
226 this->session_id = chunk_clone(notify->get_notification_data(notify));
227 DBG2(DBG_IKE, "received P2P_SESSIONID %#B", &this->session_id);
228 break;
229 }
230 case P2P_SESSIONKEY:
231 {
232 chunk_free(&this->session_key);
233 this->session_key = chunk_clone(notify->get_notification_data(notify));
234 DBG4(DBG_IKE, "received P2P_SESSIONKEY %#B", &this->session_key);
235 break;
236 }
237 case P2P_RESPONSE:
238 {
239 DBG2(DBG_IKE, "received P2P_RESPONSE notify");
240 this->response = TRUE;
241 break;
242 }
243 default:
244 break;
245 }
246 }
247 iterator->destroy(iterator);
248 }
249
250 /**
251 * Implementation of task_t.process for initiator
252 */
253 static status_t build_i(private_ike_p2p_t *this, message_t *message)
254 {
255 switch(message->get_exchange_type(message))
256 {
257 case IKE_SA_INIT:
258 {
259 peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
260 if (peer_cfg->is_mediation(peer_cfg))
261 {
262 DBG2(DBG_IKE, "adding P2P_MEDIATION");
263 message->add_notify(message, FALSE, P2P_MEDIATION, chunk_empty);
264 }
265 else
266 {
267 return SUCCESS;
268 }
269 break;
270 }
271 case IKE_AUTH:
272 {
273 if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_HERE))
274 {
275 endpoint_notify_t *endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE, NULL, NULL);
276 message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
277 endpoint->destroy(endpoint);
278 }
279 break;
280 }
281 case P2P_CONNECT:
282 {
283 id_payload_t *id_payload;
284 randomizer_t *rand = randomizer_create();
285
286 id_payload = id_payload_create_from_identification(ID_PEER, this->peer_id);
287 message->add_payload(message, (payload_t*)id_payload);
288
289 if (!this->response)
290 {
291 /* only the initiator creates a session ID. the responder returns
292 * the session ID that it received from the initiator */
293 if (rand->allocate_pseudo_random_bytes(rand,
294 P2P_SESSIONID_LEN, &this->session_id) != SUCCESS)
295 {
296 DBG1(DBG_IKE, "unable to generate session ID for P2P_CONNECT");
297 rand->destroy(rand);
298 return FAILED;
299 }
300 }
301
302 if (rand->allocate_pseudo_random_bytes(rand,
303 P2P_SESSIONKEY_LEN, &this->session_key) != SUCCESS)
304 {
305 DBG1(DBG_IKE, "unable to generate session key for P2P_CONNECT");
306 rand->destroy(rand);
307 return FAILED;
308 }
309
310 rand->destroy(rand);
311
312 message->add_notify(message, FALSE, P2P_SESSIONID, this->session_id);
313 message->add_notify(message, FALSE, P2P_SESSIONKEY, this->session_key);
314
315 if (this->response)
316 {
317 message->add_notify(message, FALSE, P2P_RESPONSE, chunk_empty);
318 }
319 else
320 {
321 /* FIXME: should we make that configurable */
322 message->add_notify(message, FALSE, P2P_CALLBACK, chunk_empty);
323 }
324
325 gather_and_add_endpoints(this, message);
326
327 break;
328 }
329 default:
330 break;
331 }
332 return NEED_MORE;
333 }
334
335 /**
336 * Implementation of task_t.process for responder
337 */
338 static status_t process_r(private_ike_p2p_t *this, message_t *message)
339 {
340 switch(message->get_exchange_type(message))
341 {
342 case P2P_CONNECT:
343 {
344 id_payload_t *id_payload;
345 id_payload = (id_payload_t*)message->get_payload(message, ID_PEER);
346 if (!id_payload)
347 {
348 DBG1(DBG_IKE, "received P2P_CONNECT without ID_PEER payload, aborting");
349 break;
350 }
351 this->peer_id = id_payload->get_identification(id_payload);
352
353 process_payloads(this, message);
354
355 if (this->callback)
356 {
357 DBG1(DBG_IKE, "received P2P_CALLBACK for '%D'", this->peer_id);
358 break;
359 }
360
361 if (!this->session_id.ptr)
362 {
363 DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONID notify, aborting");
364 this->invalid_syntax = TRUE;
365 break;
366 }
367
368 if (!this->session_key.ptr)
369 {
370 DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONKEY notify, aborting");
371 this->invalid_syntax = TRUE;
372 break;
373 }
374
375 if (!this->remote_endpoints->get_count(this->remote_endpoints))
376 {
377 DBG1(DBG_IKE, "received P2P_CONNECT without any P2P_ENDPOINT payloads, aborting");
378 this->invalid_syntax = TRUE;
379 break;
380 }
381
382 DBG1(DBG_IKE, "received P2P_CONNECT");
383 break;
384 }
385 default:
386 break;
387 }
388 return NEED_MORE;
389 }
390
391 /**
392 * Implementation of task_t.build for responder
393 */
394 static status_t build_r(private_ike_p2p_t *this, message_t *message)
395 {
396 switch(message->get_exchange_type(message))
397 {
398 case P2P_CONNECT:
399 {
400 if (this->invalid_syntax)
401 {
402 message->add_notify(message, TRUE, INVALID_SYNTAX, chunk_empty);
403 break;
404 }
405
406 if (this->callback)
407 {
408 charon->connect_manager->check_and_initiate(charon->connect_manager,
409 this->ike_sa->get_id(this->ike_sa),
410 this->ike_sa->get_my_id(this->ike_sa), this->peer_id);
411 return SUCCESS;
412 }
413
414 if (this->response)
415 {
416 /* FIXME: handle result of set_responder_data
417 * as initiator, upon receiving a response from another peer,
418 * update the checklist and start sending checks */
419 charon->connect_manager->set_responder_data(charon->connect_manager,
420 this->session_id, this->session_key, this->remote_endpoints);
421 }
422 else
423 {
424 /* FIXME: handle result of set_initiator_data
425 * as responder, create a checklist with the initiator's data */
426 charon->connect_manager->set_initiator_data(charon->connect_manager,
427 this->peer_id, this->ike_sa->get_my_id(this->ike_sa),
428 this->session_id, this->session_key, this->remote_endpoints,
429 FALSE);
430 if (this->ike_sa->respond(this->ike_sa, this->peer_id,
431 this->session_id) != SUCCESS)
432 {
433 return FAILED;
434 }
435 }
436 break;
437 }
438 default:
439 break;
440 }
441 return SUCCESS;
442 }
443
444 /**
445 * Implementation of task_t.process for initiator
446 */
447 static status_t process_i(private_ike_p2p_t *this, message_t *message)
448 {
449 switch(message->get_exchange_type(message))
450 {
451 case IKE_SA_INIT:
452 {
453 process_payloads(this, message);
454
455 if (!this->mediation)
456 {
457 DBG1(DBG_IKE, "server did not return a P2P_MEDIATION, aborting");
458 return FAILED;
459 }
460
461 return NEED_MORE;
462 }
463 case IKE_AUTH:
464 {
465 process_payloads(this, message);
466 /* FIXME: we should update the server reflexive endpoint somehow,
467 * if mobike notices a change */
468 endpoint_notify_t *reflexive;
469 if (this->remote_endpoints->get_first(this->remote_endpoints,
470 (void**)&reflexive) == SUCCESS &&
471 reflexive->get_type(reflexive) == SERVER_REFLEXIVE)
472 { /* FIXME: should we accept this endpoint even if we did not send
473 * a request? */
474 host_t *endpoint = reflexive->get_host(reflexive);
475
476 this->ike_sa->set_server_reflexive_host(this->ike_sa, endpoint->clone(endpoint));
477 }
478 /* FIXME: what if it failed? e.g. AUTH failure */
479 SIG(CHILD_UP_SUCCESS, "established mediation connection without CHILD_SA successfully");
480
481 break;
482 }
483 case P2P_CONNECT:
484 {
485 process_payloads(this, message);
486
487 if (this->failed)
488 {
489 DBG1(DBG_IKE, "peer '%D' is not online", this->peer_id);
490 /* FIXME: notify the mediated connection (job?)
491 * FIXME: probably delete the created checklist, at least as
492 * responder */
493 }
494 else
495 {
496 if (this->response)
497 {
498 /* FIXME: handle result of set_responder_data.
499 * as responder, we update the checklist and start sending checks */
500 charon->connect_manager->set_responder_data(charon->connect_manager,
501 this->session_id, this->session_key, this->local_endpoints);
502 }
503 else
504 {
505 /* FIXME: handle result of set_initiator_data
506 * as initiator, we create a checklist and set the initiator's data */
507 charon->connect_manager->set_initiator_data(charon->connect_manager,
508 this->ike_sa->get_my_id(this->ike_sa), this->peer_id,
509 this->session_id, this->session_key, this->local_endpoints,
510 TRUE);
511 }
512 }
513 break;
514 }
515 default:
516 break;
517 }
518 return SUCCESS;
519 }
520
521 /**
522 * Implementation of task_t.process for initiator (mediation server)
523 */
524 static status_t build_i_ms(private_ike_p2p_t *this, message_t *message)
525 {
526 switch(message->get_exchange_type(message))
527 {
528 case P2P_CONNECT:
529 {
530 id_payload_t *id_payload = id_payload_create_from_identification(ID_PEER, this->peer_id);
531 message->add_payload(message, (payload_t*)id_payload);
532
533 if (this->callback)
534 {
535 message->add_notify(message, FALSE, P2P_CALLBACK, chunk_empty);
536 }
537 else
538 {
539 if (this->response)
540 {
541 message->add_notify(message, FALSE, P2P_RESPONSE, chunk_empty);
542 }
543 message->add_notify(message, FALSE, P2P_SESSIONID, this->session_id);
544 message->add_notify(message, FALSE, P2P_SESSIONKEY, this->session_key);
545
546 add_endpoints_to_message(message, this->remote_endpoints);
547 }
548 break;
549 }
550 default:
551 break;
552 }
553
554 return NEED_MORE;
555 }
556
557 /**
558 * Implementation of task_t.process for responder (mediation server)
559 */
560 static status_t process_r_ms(private_ike_p2p_t *this, message_t *message)
561 {
562 switch(message->get_exchange_type(message))
563 {
564 case IKE_SA_INIT:
565 {
566 process_payloads(this, message);
567 return this->mediation ? NEED_MORE : SUCCESS;
568 }
569 case IKE_AUTH:
570 {
571 process_payloads(this, message);
572 break;
573 }
574 case P2P_CONNECT:
575 {
576 id_payload_t *id_payload;
577 id_payload = (id_payload_t*)message->get_payload(message, ID_PEER);
578 if (!id_payload)
579 {
580 DBG1(DBG_IKE, "received P2P_CONNECT without ID_PEER payload, aborting");
581 this->invalid_syntax = TRUE;
582 break;
583 }
584
585 this->peer_id = id_payload->get_identification(id_payload);
586
587 process_payloads(this, message);
588
589 if (!this->session_id.ptr)
590 {
591 DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONID notify, aborting");
592 this->invalid_syntax = TRUE;
593 break;
594 }
595
596 if (!this->session_key.ptr)
597 {
598 DBG1(DBG_IKE, "received P2P_CONNECT without P2P_SESSIONKEY notify, aborting");
599 this->invalid_syntax = TRUE;
600 break;
601 }
602
603 if (!this->remote_endpoints->get_count(this->remote_endpoints))
604 {
605 DBG1(DBG_IKE, "received P2P_CONNECT without any P2P_ENDPOINT payloads, aborting");
606 this->invalid_syntax = TRUE;
607 break;
608 }
609 break;
610 }
611 default:
612 break;
613 }
614
615 return NEED_MORE;
616 }
617
618 /**
619 * Implementation of task_t.build for responder (mediation server)
620 */
621 static status_t build_r_ms(private_ike_p2p_t *this, message_t *message)
622 {
623 switch(message->get_exchange_type(message))
624 {
625 case IKE_SA_INIT:
626 {
627 message->add_notify(message, FALSE, P2P_MEDIATION, chunk_empty);
628 return NEED_MORE;
629 }
630 case IKE_AUTH:
631 {
632 endpoint_notify_t *endpoint;
633 if (this->remote_endpoints->get_first(this->remote_endpoints, (void**)&endpoint) == SUCCESS &&
634 endpoint->get_type(endpoint) == SERVER_REFLEXIVE)
635 {
636 host_t *host = this->ike_sa->get_other_host(this->ike_sa);
637
638 DBG2(DBG_IKE, "received request for a server reflexive endpoint "
639 "sending: %#H", host);
640
641 endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE, host, NULL);
642 message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
643 }
644
645 charon->mediation_manager->update_sa_id(charon->mediation_manager,
646 this->ike_sa->get_other_id(this->ike_sa),
647 this->ike_sa->get_id(this->ike_sa));
648
649 SIG(CHILD_UP_SUCCESS, "established mediation connection without CHILD_SA successfully");
650
651 break;
652 }
653 case P2P_CONNECT:
654 {
655 if (this->invalid_syntax)
656 {
657 message->add_notify(message, TRUE, INVALID_SYNTAX, chunk_empty);
658 break;
659 }
660
661 ike_sa_id_t *peer_sa;
662 if (this->callback)
663 {
664 peer_sa = charon->mediation_manager->check_and_register(charon->mediation_manager,
665 this->peer_id, this->ike_sa->get_other_id(this->ike_sa));
666 }
667 else
668 {
669 peer_sa = charon->mediation_manager->check(charon->mediation_manager,
670 this->peer_id);
671 }
672
673 if (!peer_sa)
674 {
675 /* the peer is not online */
676 message->add_notify(message, TRUE, P2P_CONNECT_FAILED, chunk_empty);
677 break;
678 }
679
680 job_t *job = (job_t*)mediation_job_create(this->peer_id,
681 this->ike_sa->get_other_id(this->ike_sa), this->session_id,
682 this->session_key, this->remote_endpoints, this->response);
683 charon->processor->queue_job(charon->processor, job);
684
685 break;
686 }
687 default:
688 break;
689 }
690 return SUCCESS;
691 }
692
693 /**
694 * Implementation of task_t.process for initiator (mediation server)
695 */
696 static status_t process_i_ms(private_ike_p2p_t *this, message_t *message)
697 {
698 return SUCCESS;
699 }
700
701 /**
702 * Implementation of ike_p2p.connect
703 */
704 static void p2p_connect(private_ike_p2p_t *this, identification_t *peer_id)
705 {
706 this->peer_id = peer_id->clone(peer_id);
707 }
708
709 /**
710 * Implementation of ike_p2p.respond
711 */
712 static void p2p_respond(private_ike_p2p_t *this, identification_t *peer_id,
713 chunk_t session_id)
714 {
715 this->peer_id = peer_id->clone(peer_id);
716 this->session_id = chunk_clone(session_id);
717 this->response = TRUE;
718 }
719
720 /**
721 * Implementation of ike_p2p.callback
722 */
723 static void p2p_callback(private_ike_p2p_t *this, identification_t *peer_id)
724 {
725 this->peer_id = peer_id->clone(peer_id);
726 this->callback = TRUE;
727 }
728
729 /**
730 * Implementation of ike_p2p.relay
731 */
732 static void relay(private_ike_p2p_t *this, identification_t *requester, chunk_t session_id,
733 chunk_t session_key, linked_list_t *endpoints, bool response)
734 {
735 this->peer_id = requester->clone(requester);
736 this->session_id = chunk_clone(session_id);
737 this->session_key = chunk_clone(session_key);
738 this->remote_endpoints = endpoints->clone_offset(endpoints, offsetof(endpoint_notify_t, clone));
739 this->response = response;
740 }
741
742 /**
743 * Implementation of task_t.get_type
744 */
745 static task_type_t get_type(private_ike_p2p_t *this)
746 {
747 return IKE_P2P;
748 }
749
750 /**
751 * Implementation of task_t.migrate
752 */
753 static void migrate(private_ike_p2p_t *this, ike_sa_t *ike_sa)
754 {
755 this->ike_sa = ike_sa;
756 }
757
758 /**
759 * Implementation of task_t.destroy
760 */
761 static void destroy(private_ike_p2p_t *this)
762 {
763 DESTROY_IF(this->peer_id);
764
765 chunk_free(&this->session_id);
766 chunk_free(&this->session_key);
767
768 this->local_endpoints->destroy_offset(this->local_endpoints, offsetof(endpoint_notify_t, destroy));
769 this->remote_endpoints->destroy_offset(this->remote_endpoints, offsetof(endpoint_notify_t, destroy));
770
771 DESTROY_IF(this->mediated_cfg);
772 free(this);
773 }
774
775 /*
776 * Described in header.
777 */
778 ike_p2p_t *ike_p2p_create(ike_sa_t *ike_sa, bool initiator)
779 {
780 private_ike_p2p_t *this = malloc_thing(private_ike_p2p_t);
781
782 this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
783 this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
784 this->public.task.destroy = (void(*)(task_t*))destroy;
785
786 ike_sa_id_t *id = ike_sa->get_id(ike_sa);
787 if (id->is_initiator(id))
788 {
789 if (initiator)
790 {
791 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
792 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
793 }
794 else
795 {
796 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
797 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
798 }
799 }
800 else
801 {
802 /* mediation server */
803 if (initiator)
804 {
805 this->public.task.build = (status_t(*)(task_t*,message_t*))build_i_ms;
806 this->public.task.process = (status_t(*)(task_t*,message_t*))process_i_ms;
807 }
808 else
809 {
810 this->public.task.build = (status_t(*)(task_t*,message_t*))build_r_ms;
811 this->public.task.process = (status_t(*)(task_t*,message_t*))process_r_ms;
812 }
813 }
814
815 this->public.connect = (void(*)(ike_p2p_t*,identification_t*))p2p_connect;
816 this->public.respond = (void(*)(ike_p2p_t*,identification_t*,chunk_t))p2p_respond;
817 this->public.callback = (void(*)(ike_p2p_t*,identification_t*))p2p_callback;
818 this->public.relay = (void(*)(ike_p2p_t*,identification_t*,chunk_t,chunk_t,linked_list_t*,bool))relay;
819
820 this->ike_sa = ike_sa;
821 this->initiator = initiator;
822
823 this->peer_id = NULL;
824 this->session_id = chunk_empty;
825 this->session_key = chunk_empty;
826 this->local_endpoints = linked_list_create();
827 this->remote_endpoints = linked_list_create();
828 this->mediation = FALSE;
829 this->response = FALSE;
830 this->callback = FALSE;
831 this->failed = FALSE;
832 this->invalid_syntax = FALSE;
833
834 this->mediated_cfg = NULL;
835
836 return &this->public;
837 }