Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/tasks/ike_me.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2007-2008 Tobias Brunner
3: * HSR 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: enumerator_t *enumerator;
114: endpoint_notify_t *endpoint;
115:
116: enumerator = endpoints->create_enumerator(endpoints);
117: while (enumerator->enumerate(enumerator, (void**)&endpoint))
118: {
119: message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
120: }
121: enumerator->destroy(enumerator);
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: uint16_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->create_address_enumerator(charon->kernel,
138: ADDR_TYPE_REGULAR);
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) != PLV2_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: METHOD(task_t, build_i, status_t,
245: private_ike_me_t *this, message_t *message)
246: {
247: switch(message->get_exchange_type(message))
248: {
249: case IKE_SA_INIT:
250: {
251: peer_cfg_t *peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
252: if (peer_cfg->is_mediation(peer_cfg))
253: {
254: DBG2(DBG_IKE, "adding ME_MEDIATION");
255: message->add_notify(message, FALSE, ME_MEDIATION, chunk_empty);
256: }
257: else
258: {
259: return SUCCESS;
260: }
261: break;
262: }
263: case IKE_AUTH:
264: {
265: if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_HERE))
266: {
267: endpoint_notify_t *endpoint;
268: endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE,
269: NULL, NULL);
270: message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
271: endpoint->destroy(endpoint);
272: }
273: break;
274: }
275: case ME_CONNECT:
276: {
277: rng_t *rng;
278: id_payload_t *id_payload;
279: id_payload = id_payload_create_from_identification(PLV2_ID_PEER,
280: this->peer_id);
281: message->add_payload(message, (payload_t*)id_payload);
282:
283: rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
284: if (!rng)
285: {
286: DBG1(DBG_IKE, "unable to generate connect ID for ME_CONNECT");
287: return FAILED;
288: }
289: if (!this->response)
290: {
291: /* only the initiator creates a connect ID. the responder
292: * returns the connect ID that it received from the initiator */
293: if (!rng->allocate_bytes(rng, ME_CONNECTID_LEN,
294: &this->connect_id))
295: {
296: DBG1(DBG_IKE, "unable to generate ID for ME_CONNECT");
297: rng->destroy(rng);
298: return FAILED;
299: }
300: }
301: if (!rng->allocate_bytes(rng, ME_CONNECTKEY_LEN,
302: &this->connect_key))
303: {
304: DBG1(DBG_IKE, "unable to generate connect key for ME_CONNECT");
305: rng->destroy(rng);
306: return FAILED;
307: }
308: rng->destroy(rng);
309:
310: message->add_notify(message, FALSE, ME_CONNECTID, this->connect_id);
311: message->add_notify(message, FALSE, ME_CONNECTKEY, this->connect_key);
312:
313: if (this->response)
314: {
315: message->add_notify(message, FALSE, ME_RESPONSE, chunk_empty);
316: }
317: else
318: {
319: /* FIXME: should we make this configurable? */
320: message->add_notify(message, FALSE, ME_CALLBACK, chunk_empty);
321: }
322:
323: gather_and_add_endpoints(this, message);
324:
325: break;
326: }
327: default:
328: break;
329: }
330: return NEED_MORE;
331: }
332:
333: METHOD(task_t, process_r, status_t,
334: private_ike_me_t *this, message_t *message)
335: {
336: switch(message->get_exchange_type(message))
337: {
338: case ME_CONNECT:
339: {
340: id_payload_t *id_payload;
341: id_payload = (id_payload_t*)message->get_payload(message, PLV2_ID_PEER);
342: if (!id_payload)
343: {
344: DBG1(DBG_IKE, "received ME_CONNECT without ID_PEER payload"
345: ", aborting");
346: break;
347: }
348: this->peer_id = id_payload->get_identification(id_payload);
349:
350: process_payloads(this, message);
351:
352: if (this->callback)
353: {
354: DBG1(DBG_IKE, "received ME_CALLBACK for '%Y'", this->peer_id);
355: break;
356: }
357:
358: if (!this->connect_id.ptr)
359: {
360: DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTID notify"
361: ", aborting");
362: this->invalid_syntax = TRUE;
363: break;
364: }
365:
366: if (!this->connect_key.ptr)
367: {
368: DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTKEY "
369: "notify, aborting");
370: this->invalid_syntax = TRUE;
371: break;
372: }
373:
374: if (!this->remote_endpoints->get_count(this->remote_endpoints))
375: {
376: DBG1(DBG_IKE, "received ME_CONNECT without any ME_ENDPOINT "
377: "payloads, aborting");
378: this->invalid_syntax = TRUE;
379: break;
380: }
381:
382: DBG1(DBG_IKE, "received ME_CONNECT");
383: break;
384: }
385: default:
386: break;
387: }
388: return NEED_MORE;
389: }
390:
391: METHOD(task_t, build_r, status_t,
392: private_ike_me_t *this, message_t *message)
393: {
394: switch(message->get_exchange_type(message))
395: {
396: case ME_CONNECT:
397: {
398: if (this->invalid_syntax)
399: {
400: message->add_notify(message, TRUE, INVALID_SYNTAX, chunk_empty);
401: break;
402: }
403:
404: if (this->callback)
405: {
406: /* we got a callback from the mediation server, initiate the
407: * queued mediated connection */
408: charon->connect_manager->check_and_initiate(
409: charon->connect_manager,
410: this->ike_sa->get_id(this->ike_sa),
411: this->ike_sa->get_my_id(this->ike_sa), this->peer_id);
412: return SUCCESS;
413: }
414:
415: if (this->response)
416: {
417: /* FIXME: handle result of set_responder_data
418: * as initiator, upon receiving a response from another peer,
419: * update the checklist and start sending checks */
420: charon->connect_manager->set_responder_data(
421: charon->connect_manager,
422: this->connect_id, this->connect_key,
423: this->remote_endpoints);
424: }
425: else
426: {
427: /* FIXME: handle result of set_initiator_data
428: * as responder, create a checklist with the initiator's data */
429: charon->connect_manager->set_initiator_data(
430: charon->connect_manager,
431: this->peer_id, this->ike_sa->get_my_id(this->ike_sa),
432: this->connect_id, this->connect_key,
433: this->remote_endpoints, FALSE);
434: if (this->ike_sa->respond(this->ike_sa, this->peer_id,
435: this->connect_id) != SUCCESS)
436: {
437: return FAILED;
438: }
439: }
440: break;
441: }
442: default:
443: break;
444: }
445: return SUCCESS;
446: }
447:
448: METHOD(task_t, process_i, status_t,
449: private_ike_me_t *this, message_t *message)
450: {
451: switch(message->get_exchange_type(message))
452: {
453: case IKE_SA_INIT:
454: {
455: process_payloads(this, message);
456: if (!this->mediation)
457: {
458: DBG1(DBG_IKE, "server did not return a ME_MEDIATION, aborting");
459: return FAILED;
460: }
461: /* if we are on a mediation connection we switch to port 4500 even
462: * if no NAT is detected. */
463: this->ike_sa->float_ports(this->ike_sa);
464: return NEED_MORE;
465: }
466: case IKE_AUTH:
467: {
468: process_payloads(this, message);
469: /* FIXME: we should update the server reflexive endpoint somehow,
470: * if mobike notices a change */
471: endpoint_notify_t *reflexive;
472: if (this->remote_endpoints->get_first(this->remote_endpoints,
473: (void**)&reflexive) == SUCCESS &&
474: reflexive->get_type(reflexive) == SERVER_REFLEXIVE)
475: { /* FIXME: should we accept this endpoint even if we did not send
476: * a request? */
477: host_t *endpoint = reflexive->get_host(reflexive);
478: endpoint = endpoint->clone(endpoint);
479: this->ike_sa->set_server_reflexive_host(this->ike_sa, endpoint);
480: }
481: break;
482: }
483: case ME_CONNECT:
484: {
485: process_payloads(this, message);
486:
487: if (this->failed)
488: {
489: DBG1(DBG_IKE, "peer '%Y' is not online", this->peer_id);
490: /* FIXME: notify the mediated connection (job?) */
491: }
492: else
493: {
494: if (this->response)
495: {
496: /* FIXME: handle result of set_responder_data. */
497: /* as responder, we update the checklist and start sending
498: * checks */
499: charon->connect_manager->set_responder_data(
500: charon->connect_manager, this->connect_id,
501: this->connect_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
507: * initiator's data */
508: charon->connect_manager->set_initiator_data(
509: charon->connect_manager,
510: this->ike_sa->get_my_id(this->ike_sa),
511: this->peer_id, this->connect_id, this->connect_key,
512: this->local_endpoints, TRUE);
513: /* FIXME: also start a timer for the whole transaction
514: * (maybe within the connect_manager?) */
515: }
516: }
517: break;
518: }
519: default:
520: break;
521: }
522: return SUCCESS;
523: }
524:
525: /**
526: * For mediation server
527: */
528: METHOD(task_t, build_i_ms, status_t,
529: private_ike_me_t *this, message_t *message)
530: {
531: switch(message->get_exchange_type(message))
532: {
533: case ME_CONNECT:
534: {
535: id_payload_t *id_payload;
536: id_payload = id_payload_create_from_identification(PLV2_ID_PEER,
537: this->peer_id);
538: message->add_payload(message, (payload_t*)id_payload);
539:
540: if (this->callback)
541: {
542: message->add_notify(message, FALSE, ME_CALLBACK, chunk_empty);
543: }
544: else
545: {
546: if (this->response)
547: {
548: message->add_notify(message, FALSE, ME_RESPONSE,
549: chunk_empty);
550: }
551: message->add_notify(message, FALSE, ME_CONNECTID,
552: this->connect_id);
553: message->add_notify(message, FALSE, ME_CONNECTKEY,
554: this->connect_key);
555: add_endpoints_to_message(message, this->remote_endpoints);
556: }
557: break;
558: }
559: default:
560: break;
561: }
562: return NEED_MORE;
563: }
564:
565: /**
566: * For mediation server
567: */
568: METHOD(task_t, process_r_ms, status_t,
569: private_ike_me_t *this, message_t *message)
570: {
571: switch(message->get_exchange_type(message))
572: {
573: case IKE_SA_INIT:
574: {
575: /* FIXME: we should check for SA* and TS* payloads. if there are
576: * any, send NO_ADDITIONAL_SAS back and delete this SA */
577: process_payloads(this, message);
578: return this->mediation ? NEED_MORE : SUCCESS;
579: }
580: case IKE_AUTH:
581: {
582: /* FIXME: we should check whether the current peer_config is
583: * configured as mediation connection */
584: process_payloads(this, message);
585: break;
586: }
587: case CREATE_CHILD_SA:
588: {
589: /* FIXME: if this is not to rekey the IKE SA we have to return a
590: * NO_ADDITIONAL_SAS and then delete the SA */
591: break;
592: }
593: case ME_CONNECT:
594: {
595: id_payload_t *id_payload;
596: id_payload = (id_payload_t*)message->get_payload(message, PLV2_ID_PEER);
597: if (!id_payload)
598: {
599: DBG1(DBG_IKE, "received ME_CONNECT without ID_PEER payload"
600: ", aborting");
601: this->invalid_syntax = TRUE;
602: break;
603: }
604: this->peer_id = id_payload->get_identification(id_payload);
605:
606: process_payloads(this, message);
607:
608: if (!this->connect_id.ptr)
609: {
610: DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTID notify"
611: ", aborting");
612: this->invalid_syntax = TRUE;
613: break;
614: }
615:
616: if (!this->connect_key.ptr)
617: {
618: DBG1(DBG_IKE, "received ME_CONNECT without ME_CONNECTKEY notify"
619: ", aborting");
620: this->invalid_syntax = TRUE;
621: break;
622: }
623:
624: if (!this->remote_endpoints->get_count(this->remote_endpoints))
625: {
626: DBG1(DBG_IKE, "received ME_CONNECT without any ME_ENDPOINT "
627: "payloads, aborting");
628: this->invalid_syntax = TRUE;
629: break;
630: }
631: break;
632: }
633: default:
634: break;
635: }
636: return NEED_MORE;
637: }
638:
639: /**
640: * For mediation server
641: */
642: METHOD(task_t, build_r_ms, status_t,
643: private_ike_me_t *this, message_t *message)
644: {
645: switch(message->get_exchange_type(message))
646: {
647: case IKE_SA_INIT:
648: {
649: message->add_notify(message, FALSE, ME_MEDIATION, chunk_empty);
650: return NEED_MORE;
651: }
652: case IKE_AUTH:
653: {
654: endpoint_notify_t *endpoint;
655: if (this->remote_endpoints->get_first(this->remote_endpoints,
656: (void**)&endpoint) == SUCCESS &&
657: endpoint->get_type(endpoint) == SERVER_REFLEXIVE)
658: {
659: host_t *host = this->ike_sa->get_other_host(this->ike_sa);
660: DBG2(DBG_IKE, "received request for a server reflexive "
661: "endpoint sending: %#H", host);
662: endpoint = endpoint_notify_create_from_host(SERVER_REFLEXIVE,
663: host, NULL);
664: message->add_payload(message, (payload_t*)endpoint->build_notify(endpoint));
665: endpoint->destroy(endpoint);
666: }
667: this->ike_sa->act_as_mediation_server(this->ike_sa);
668: break;
669: }
670: case ME_CONNECT:
671: {
672: if (this->invalid_syntax)
673: {
674: message->add_notify(message, TRUE, INVALID_SYNTAX, chunk_empty);
675: break;
676: }
677:
678: ike_sa_id_t *peer_sa;
679: if (this->callback)
680: {
681: peer_sa = charon->mediation_manager->check_and_register(
682: charon->mediation_manager, this->peer_id,
683: this->ike_sa->get_other_id(this->ike_sa));
684: }
685: else
686: {
687: peer_sa = charon->mediation_manager->check(
688: charon->mediation_manager, this->peer_id);
689: }
690:
691: if (!peer_sa)
692: {
693: /* the peer is not online */
694: message->add_notify(message, TRUE, ME_CONNECT_FAILED,
695: chunk_empty);
696: break;
697: }
698:
699: job_t *job = (job_t*)mediation_job_create(this->peer_id,
700: this->ike_sa->get_other_id(this->ike_sa), this->connect_id,
701: this->connect_key, this->remote_endpoints, this->response);
702: lib->processor->queue_job(lib->processor, job);
703: break;
704: }
705: default:
706: break;
707: }
708: return SUCCESS;
709: }
710:
711: /**
712: * For mediation server
713: */
714: METHOD(task_t, process_i_ms, status_t,
715: private_ike_me_t *this, message_t *message)
716: {
717: /* FIXME: theoretically we should be prepared to receive a ME_CONNECT_FAILED
718: * here if the responding peer is not able to proceed. in this case we shall
719: * notify the initiating peer with a ME_CONNECT request containing only a
720: * ME_CONNECT_FAILED */
721: return SUCCESS;
722: }
723:
724: METHOD(ike_me_t, me_connect, void,
725: private_ike_me_t *this, identification_t *peer_id)
726: {
727: this->peer_id = peer_id->clone(peer_id);
728: }
729:
730: METHOD(ike_me_t, me_respond, void,
731: private_ike_me_t *this, identification_t *peer_id, chunk_t connect_id)
732: {
733: this->peer_id = peer_id->clone(peer_id);
734: this->connect_id = chunk_clone(connect_id);
735: this->response = TRUE;
736: }
737:
738: METHOD(ike_me_t, me_callback, void,
739: private_ike_me_t *this, identification_t *peer_id)
740: {
741: this->peer_id = peer_id->clone(peer_id);
742: this->callback = TRUE;
743: }
744:
745: METHOD(ike_me_t, relay, void,
746: private_ike_me_t *this, identification_t *requester, chunk_t connect_id,
747: chunk_t connect_key, linked_list_t *endpoints, bool response)
748: {
749: this->peer_id = requester->clone(requester);
750: this->connect_id = chunk_clone(connect_id);
751: this->connect_key = chunk_clone(connect_key);
752:
753: this->remote_endpoints->destroy_offset(this->remote_endpoints,
754: offsetof(endpoint_notify_t, destroy));
755: this->remote_endpoints = endpoints->clone_offset(endpoints,
756: offsetof(endpoint_notify_t, clone));
757:
758: this->response = response;
759: }
760:
761: METHOD(task_t, get_type, task_type_t,
762: private_ike_me_t *this)
763: {
764: return TASK_IKE_ME;
765: }
766:
767: METHOD(task_t, migrate, void,
768: private_ike_me_t *this, ike_sa_t *ike_sa)
769: {
770: this->ike_sa = ike_sa;
771: }
772:
773: METHOD(task_t, destroy, void,
774: private_ike_me_t *this)
775: {
776: DESTROY_IF(this->peer_id);
777:
778: chunk_free(&this->connect_id);
779: chunk_free(&this->connect_key);
780:
781: this->local_endpoints->destroy_offset(this->local_endpoints,
782: offsetof(endpoint_notify_t, destroy));
783: this->remote_endpoints->destroy_offset(this->remote_endpoints,
784: offsetof(endpoint_notify_t, destroy));
785:
786: DESTROY_IF(this->mediated_cfg);
787: free(this);
788: }
789:
790: /*
791: * Described in header.
792: */
793: ike_me_t *ike_me_create(ike_sa_t *ike_sa, bool initiator)
794: {
795: private_ike_me_t *this;
796:
797: INIT(this,
798: .public = {
799: .task = {
800: .get_type = _get_type,
801: .migrate = _migrate,
802: .destroy = _destroy,
803: },
804: .connect = _me_connect,
805: .respond = _me_respond,
806: .callback = _me_callback,
807: .relay = _relay,
808: },
809: .ike_sa = ike_sa,
810: .initiator = initiator,
811: .local_endpoints = linked_list_create(),
812: .remote_endpoints = linked_list_create(),
813: );
814:
815: if (ike_sa->has_condition(ike_sa, COND_ORIGINAL_INITIATOR))
816: {
817: if (initiator)
818: {
819: this->public.task.build = _build_i;
820: this->public.task.process = _process_i;
821: }
822: else
823: {
824: this->public.task.build = _build_r;
825: this->public.task.process = _process_r;
826: }
827: }
828: else
829: {
830: /* mediation server */
831: if (initiator)
832: {
833: this->public.task.build = _build_i_ms;
834: this->public.task.process = _process_i_ms;
835: }
836: else
837: {
838: this->public.task.build = _build_r_ms;
839: this->public.task.process = _process_r_ms;
840: }
841: }
842:
843: return &this->public;
844: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>