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