/src/strongswan/src/libcharon/processing/jobs/migrate_job.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2008 Andreas Steffen |
3 | | * |
4 | | * Copyright (C) secunet Security Networks AG |
5 | | * |
6 | | * This program is free software; you can redistribute it and/or modify it |
7 | | * under the terms of the GNU General Public License as published by the |
8 | | * Free Software Foundation; either version 2 of the License, or (at your |
9 | | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. |
10 | | * |
11 | | * This program is distributed in the hope that it will be useful, but |
12 | | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
13 | | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
14 | | * for more details. |
15 | | */ |
16 | | |
17 | | #include "migrate_job.h" |
18 | | |
19 | | #include <daemon.h> |
20 | | |
21 | | #include <config/child_cfg.h> |
22 | | |
23 | | |
24 | | typedef struct private_migrate_job_t private_migrate_job_t; |
25 | | |
26 | | /** |
27 | | * Private data of a migrate_job_t object. |
28 | | */ |
29 | | struct private_migrate_job_t { |
30 | | /** |
31 | | * Public migrate_job_t interface. |
32 | | */ |
33 | | migrate_job_t public; |
34 | | |
35 | | /** |
36 | | * reqid of the CHILD_SA if it already exists |
37 | | */ |
38 | | uint32_t reqid; |
39 | | |
40 | | /** |
41 | | * source traffic selector |
42 | | */ |
43 | | traffic_selector_t *src_ts; |
44 | | |
45 | | /** |
46 | | * destination traffic selector |
47 | | */ |
48 | | traffic_selector_t *dst_ts; |
49 | | |
50 | | /** |
51 | | * local host address to be used for IKE |
52 | | */ |
53 | | host_t *local; |
54 | | |
55 | | /** |
56 | | * remote host address to be used for IKE |
57 | | */ |
58 | | host_t *remote; |
59 | | }; |
60 | | |
61 | | METHOD(job_t, destroy, void, |
62 | | private_migrate_job_t *this) |
63 | 0 | { |
64 | 0 | DESTROY_IF(this->src_ts); |
65 | 0 | DESTROY_IF(this->dst_ts); |
66 | 0 | DESTROY_IF(this->local); |
67 | 0 | DESTROY_IF(this->remote); |
68 | 0 | free(this); |
69 | 0 | } |
70 | | |
71 | | METHOD(job_t, execute, job_requeue_t, |
72 | | private_migrate_job_t *this) |
73 | 0 | { |
74 | 0 | enumerator_t *ike_sas, *children; |
75 | 0 | ike_sa_t *ike_sa; |
76 | |
|
77 | 0 | ike_sas = charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager, |
78 | 0 | TRUE); |
79 | 0 | while (ike_sas->enumerate(ike_sas, &ike_sa)) |
80 | 0 | { |
81 | 0 | child_sa_t *current, *child_sa = NULL; |
82 | 0 | linked_list_t *vips; |
83 | 0 | status_t status; |
84 | 0 | host_t *host; |
85 | |
|
86 | 0 | children = ike_sa->create_child_sa_enumerator(ike_sa); |
87 | 0 | while (children->enumerate(children, ¤t)) |
88 | 0 | { |
89 | 0 | if (current->get_reqid(current) == this->reqid) |
90 | 0 | { |
91 | 0 | child_sa = current; |
92 | 0 | break; |
93 | 0 | } |
94 | 0 | } |
95 | 0 | children->destroy(children); |
96 | |
|
97 | 0 | if (!child_sa) |
98 | 0 | { |
99 | 0 | continue; |
100 | 0 | } |
101 | | |
102 | 0 | DBG2(DBG_JOB, "found CHILD_SA with reqid {%u}", this->reqid); |
103 | |
|
104 | 0 | ike_sa->set_kmaddress(ike_sa, this->local, this->remote); |
105 | |
|
106 | 0 | host = this->local->clone(this->local); |
107 | 0 | host->set_port(host, charon->socket->get_port(charon->socket, FALSE)); |
108 | 0 | ike_sa->set_my_host(ike_sa, host); |
109 | |
|
110 | 0 | host = this->remote->clone(this->remote); |
111 | 0 | host->set_port(host, IKEV2_UDP_PORT); |
112 | 0 | ike_sa->set_other_host(ike_sa, host); |
113 | |
|
114 | 0 | vips = linked_list_create_from_enumerator( |
115 | 0 | ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE)); |
116 | |
|
117 | 0 | status = child_sa->update(child_sa, this->local, this->remote, vips, |
118 | 0 | ike_sa->has_condition(ike_sa, COND_NAT_ANY)); |
119 | 0 | switch (status) |
120 | 0 | { |
121 | 0 | case NOT_SUPPORTED: |
122 | 0 | ike_sa->rekey_child_sa(ike_sa, child_sa->get_protocol(child_sa), |
123 | 0 | child_sa->get_spi(child_sa, TRUE)); |
124 | 0 | break; |
125 | 0 | case SUCCESS: |
126 | 0 | charon->child_sa_manager->remove(charon->child_sa_manager, |
127 | 0 | child_sa); |
128 | 0 | charon->child_sa_manager->add(charon->child_sa_manager, |
129 | 0 | child_sa, ike_sa); |
130 | 0 | default: |
131 | 0 | break; |
132 | 0 | } |
133 | 0 | vips->destroy(vips); |
134 | 0 | } |
135 | 0 | ike_sas->destroy(ike_sas); |
136 | 0 | return JOB_REQUEUE_NONE; |
137 | 0 | } |
138 | | |
139 | | METHOD(job_t, get_priority, job_priority_t, |
140 | | private_migrate_job_t *this) |
141 | 0 | { |
142 | 0 | return JOB_PRIO_MEDIUM; |
143 | 0 | } |
144 | | |
145 | | /* |
146 | | * Described in header |
147 | | */ |
148 | | migrate_job_t *migrate_job_create(uint32_t reqid, |
149 | | traffic_selector_t *src_ts, |
150 | | traffic_selector_t *dst_ts, |
151 | | policy_dir_t dir, |
152 | | host_t *local, host_t *remote) |
153 | 0 | { |
154 | 0 | private_migrate_job_t *this; |
155 | |
|
156 | 0 | INIT(this, |
157 | 0 | .public = { |
158 | 0 | .job_interface = { |
159 | 0 | .execute = _execute, |
160 | 0 | .get_priority = _get_priority, |
161 | 0 | .destroy = _destroy, |
162 | 0 | }, |
163 | 0 | }, |
164 | 0 | .reqid = reqid, |
165 | 0 | .src_ts = (dir == POLICY_OUT) ? src_ts : dst_ts, |
166 | 0 | .dst_ts = (dir == POLICY_OUT) ? dst_ts : src_ts, |
167 | 0 | .local = local, |
168 | 0 | .remote = remote, |
169 | 0 | ); |
170 | |
|
171 | 0 | return &this->public; |
172 | 0 | } |