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