]>
Commit | Line | Data |
---|---|---|
e0fe7651 | 1 | /* |
9486a2e5 | 2 | * Copyright (C) 2012-2019 Tobias Brunner |
e0fe7651 MW |
3 | * Copyright (C) 2005-2007 Martin Willi |
4 | * Copyright (C) 2005 Jan Hutter | |
19ef2aec TB |
5 | * |
6 | * Copyright (C) secunet Security Networks AG | |
e0fe7651 MW |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify it | |
9 | * under the terms of the GNU General Public License as published by the | |
10 | * Free Software Foundation; either version 2 of the License, or (at your | |
11 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, but | |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
15 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 | * for more details. | |
17 | */ | |
18 | ||
ab13364c | 19 | #define _GNU_SOURCE /* for stdndup() */ |
e0fe7651 MW |
20 | #include <string.h> |
21 | ||
ab13364c | 22 | #include "ike_cfg.h" |
035930fc | 23 | |
ab13364c | 24 | #include <daemon.h> |
e0fe7651 | 25 | |
cf62d073 MW |
26 | ENUM(ike_version_names, IKE_ANY, IKEV2, |
27 | "IKEv1/2", | |
28 | "IKEv1", | |
29 | "IKEv2", | |
30 | ); | |
31 | ||
e0fe7651 MW |
32 | typedef struct private_ike_cfg_t private_ike_cfg_t; |
33 | ||
34 | /** | |
35 | * Private data of an ike_cfg_t object | |
36 | */ | |
37 | struct private_ike_cfg_t { | |
38 | ||
39 | /** | |
40 | * Public part | |
41 | */ | |
42 | ike_cfg_t public; | |
7daf5226 | 43 | |
e0fe7651 MW |
44 | /** |
45 | * Number of references hold by others to this ike_cfg | |
46 | */ | |
47 | refcount_t refcount; | |
48 | ||
9fc7cc6f MW |
49 | /** |
50 | * IKE version to use | |
51 | */ | |
52 | ike_version_t version; | |
53 | ||
e0fe7651 | 54 | /** |
3070697f | 55 | * Address list string for local host |
e0fe7651 | 56 | */ |
5a22a021 | 57 | char *me; |
e0fe7651 MW |
58 | |
59 | /** | |
3070697f | 60 | * Address list string for remote host |
7daf5226 | 61 | */ |
5a22a021 | 62 | char *other; |
7daf5226 | 63 | |
1d315bdd | 64 | /** |
3070697f | 65 | * Local single host or DNS names, as allocated char* |
1d315bdd | 66 | */ |
3070697f | 67 | linked_list_t *my_hosts; |
1d315bdd AS |
68 | |
69 | /** | |
3070697f | 70 | * Remote single host or DNS names, as allocated char* |
1d315bdd | 71 | */ |
3070697f MW |
72 | linked_list_t *other_hosts; |
73 | ||
74 | /** | |
75 | * Local ranges/subnets this config matches to, as traffic_selector_t* | |
76 | */ | |
77 | linked_list_t *my_ranges; | |
78 | ||
79 | /** | |
80 | * Remote ranges/subnets this config matches to, as traffic_selector_t* | |
81 | */ | |
82 | linked_list_t *other_ranges; | |
1d315bdd | 83 | |
4e18490e MW |
84 | /** |
85 | * our source port | |
86 | */ | |
b12c53ce | 87 | uint16_t my_port; |
4e18490e MW |
88 | |
89 | /** | |
90 | * destination port | |
91 | */ | |
b12c53ce | 92 | uint16_t other_port; |
4e18490e | 93 | |
e0fe7651 MW |
94 | /** |
95 | * should we send a certificate request? | |
96 | */ | |
97 | bool certreq; | |
7daf5226 | 98 | |
15612b3a JFH |
99 | /** |
100 | * should we send an OCSP status request? | |
101 | */ | |
102 | bool ocsp_certreq; | |
103 | ||
f53b74c9 MW |
104 | /** |
105 | * enforce UDP encapsulation | |
106 | */ | |
107 | bool force_encap; | |
7daf5226 | 108 | |
97973f86 | 109 | /** |
ddb083c1 | 110 | * use IKE fragmentation |
97973f86 | 111 | */ |
365d9a6f | 112 | fragmentation_t fragmentation; |
97973f86 | 113 | |
ddb083c1 TB |
114 | /** |
115 | * childless IKE_SAs | |
116 | */ | |
117 | childless_t childless; | |
118 | ||
306a269e MW |
119 | /** |
120 | * DSCP value to use on sent IKE packets | |
121 | */ | |
b12c53ce | 122 | uint8_t dscp; |
306a269e | 123 | |
e0fe7651 MW |
124 | /** |
125 | * List of proposals to use | |
126 | */ | |
127 | linked_list_t *proposals; | |
128 | }; | |
129 | ||
9fc7cc6f MW |
130 | METHOD(ike_cfg_t, get_version, ike_version_t, |
131 | private_ike_cfg_t *this) | |
132 | { | |
133 | return this->version; | |
134 | } | |
135 | ||
deac3a0a MW |
136 | METHOD(ike_cfg_t, send_certreq, bool, |
137 | private_ike_cfg_t *this) | |
e0fe7651 MW |
138 | { |
139 | return this->certreq; | |
140 | } | |
7daf5226 | 141 | |
15612b3a JFH |
142 | METHOD(ike_cfg_t, send_ocsp_certreq, bool, |
143 | private_ike_cfg_t *this) | |
144 | { | |
145 | return this->ocsp_certreq; | |
146 | } | |
147 | ||
deac3a0a MW |
148 | METHOD(ike_cfg_t, force_encap_, bool, |
149 | private_ike_cfg_t *this) | |
f53b74c9 MW |
150 | { |
151 | return this->force_encap; | |
152 | } | |
e0fe7651 | 153 | |
365d9a6f | 154 | METHOD(ike_cfg_t, fragmentation, fragmentation_t, |
97973f86 TB |
155 | private_ike_cfg_t *this) |
156 | { | |
157 | return this->fragmentation; | |
158 | } | |
159 | ||
ddb083c1 TB |
160 | METHOD(ike_cfg_t, childless, childless_t, |
161 | private_ike_cfg_t *this) | |
162 | { | |
163 | return this->childless; | |
164 | } | |
165 | ||
3070697f MW |
166 | /** |
167 | * Common function for resolve_me/other | |
168 | */ | |
b12c53ce | 169 | static host_t* resolve(linked_list_t *hosts, int family, uint16_t port) |
3070697f MW |
170 | { |
171 | enumerator_t *enumerator; | |
172 | host_t *host = NULL; | |
173 | bool tried = FALSE; | |
174 | char *str; | |
175 | ||
176 | enumerator = hosts->create_enumerator(hosts); | |
177 | while (enumerator->enumerate(enumerator, &str)) | |
178 | { | |
179 | host = host_create_from_dns(str, family, port); | |
180 | if (host) | |
181 | { | |
182 | break; | |
183 | } | |
184 | tried = TRUE; | |
185 | } | |
186 | enumerator->destroy(enumerator); | |
187 | ||
188 | if (!host && !tried) | |
189 | { | |
190 | /* we have no single host configured, return %any */ | |
191 | host = host_create_any(family ?: AF_INET); | |
192 | host->set_port(host, port); | |
193 | } | |
194 | return host; | |
195 | } | |
196 | ||
e743275c MW |
197 | METHOD(ike_cfg_t, resolve_me, host_t*, |
198 | private_ike_cfg_t *this, int family) | |
199 | { | |
3070697f | 200 | return resolve(this->my_hosts, family, this->my_port); |
e743275c MW |
201 | } |
202 | ||
203 | METHOD(ike_cfg_t, resolve_other, host_t*, | |
204 | private_ike_cfg_t *this, int family) | |
205 | { | |
3070697f | 206 | return resolve(this->other_hosts, family, this->other_port); |
e743275c MW |
207 | } |
208 | ||
3070697f MW |
209 | /** |
210 | * Common function for match_me/other | |
211 | */ | |
212 | static u_int match(linked_list_t *hosts, linked_list_t *ranges, host_t *cand) | |
6f666192 | 213 | { |
3070697f MW |
214 | enumerator_t *enumerator; |
215 | traffic_selector_t *ts; | |
216 | char *str; | |
217 | host_t *host; | |
b12c53ce | 218 | uint8_t mask; |
3070697f MW |
219 | u_int quality = 0; |
220 | ||
221 | /* try single hosts first */ | |
222 | enumerator = hosts->create_enumerator(hosts); | |
223 | while (enumerator->enumerate(enumerator, &str)) | |
6f666192 | 224 | { |
3070697f MW |
225 | host = host_create_from_dns(str, cand->get_family(cand), 0); |
226 | if (host) | |
6f666192 | 227 | { |
3070697f MW |
228 | if (host->ip_equals(host, cand)) |
229 | { | |
230 | quality = max(quality, 128 + 1); | |
231 | } | |
232 | if (host->is_anyaddr(host)) | |
233 | { | |
234 | quality = max(quality, 1); | |
235 | } | |
236 | host->destroy(host); | |
6f666192 | 237 | } |
3070697f MW |
238 | } |
239 | enumerator->destroy(enumerator); | |
240 | ||
241 | /* then ranges/subnets */ | |
242 | enumerator = ranges->create_enumerator(ranges); | |
243 | while (enumerator->enumerate(enumerator, &ts)) | |
244 | { | |
245 | if (ts->includes(ts, cand)) | |
6f666192 | 246 | { |
3070697f MW |
247 | if (ts->to_subnet(ts, &host, &mask)) |
248 | { | |
249 | quality = max(quality, mask + 1); | |
3070697f MW |
250 | } |
251 | else | |
252 | { | |
253 | quality = max(quality, 1); | |
254 | } | |
a09e79ed | 255 | host->destroy(host); |
6f666192 | 256 | } |
6f666192 | 257 | } |
3070697f MW |
258 | enumerator->destroy(enumerator); |
259 | ||
6f666192 MW |
260 | return quality; |
261 | } | |
262 | ||
3070697f | 263 | METHOD(ike_cfg_t, match_me, u_int, |
6f666192 MW |
264 | private_ike_cfg_t *this, host_t *host) |
265 | { | |
3070697f MW |
266 | return match(this->my_hosts, this->my_ranges, host); |
267 | } | |
6f666192 | 268 | |
3070697f MW |
269 | METHOD(ike_cfg_t, match_other, u_int, |
270 | private_ike_cfg_t *this, host_t *host) | |
271 | { | |
272 | return match(this->other_hosts, this->other_ranges, host); | |
6f666192 MW |
273 | } |
274 | ||
deac3a0a | 275 | METHOD(ike_cfg_t, get_my_addr, char*, |
beffdc6a | 276 | private_ike_cfg_t *this) |
e0fe7651 | 277 | { |
5a22a021 | 278 | return this->me; |
e0fe7651 MW |
279 | } |
280 | ||
deac3a0a | 281 | METHOD(ike_cfg_t, get_other_addr, char*, |
beffdc6a | 282 | private_ike_cfg_t *this) |
e0fe7651 | 283 | { |
5a22a021 | 284 | return this->other; |
e0fe7651 MW |
285 | } |
286 | ||
b12c53ce | 287 | METHOD(ike_cfg_t, get_my_port, uint16_t, |
4e18490e MW |
288 | private_ike_cfg_t *this) |
289 | { | |
290 | return this->my_port; | |
291 | } | |
292 | ||
b12c53ce | 293 | METHOD(ike_cfg_t, get_other_port, uint16_t, |
4e18490e MW |
294 | private_ike_cfg_t *this) |
295 | { | |
296 | return this->other_port; | |
297 | } | |
298 | ||
b12c53ce | 299 | METHOD(ike_cfg_t, get_dscp, uint8_t, |
306a269e MW |
300 | private_ike_cfg_t *this) |
301 | { | |
302 | return this->dscp; | |
303 | } | |
304 | ||
deac3a0a MW |
305 | METHOD(ike_cfg_t, add_proposal, void, |
306 | private_ike_cfg_t *this, proposal_t *proposal) | |
e0fe7651 | 307 | { |
3312c447 MW |
308 | if (proposal) |
309 | { | |
310 | this->proposals->insert_last(this->proposals, proposal); | |
311 | } | |
e0fe7651 MW |
312 | } |
313 | ||
deac3a0a MW |
314 | METHOD(ike_cfg_t, get_proposals, linked_list_t*, |
315 | private_ike_cfg_t *this) | |
e0fe7651 | 316 | { |
deac3a0a | 317 | enumerator_t *enumerator; |
e0fe7651 | 318 | proposal_t *current; |
deac3a0a | 319 | linked_list_t *proposals; |
7daf5226 | 320 | |
deac3a0a MW |
321 | proposals = linked_list_create(); |
322 | enumerator = this->proposals->create_enumerator(this->proposals); | |
323 | while (enumerator->enumerate(enumerator, ¤t)) | |
e0fe7651 | 324 | { |
a2cb2c9c | 325 | current = current->clone(current, 0); |
deac3a0a | 326 | proposals->insert_last(proposals, current); |
e0fe7651 | 327 | } |
deac3a0a | 328 | enumerator->destroy(enumerator); |
a21fac9a TB |
329 | |
330 | DBG2(DBG_CFG, "configured proposals: %#P", proposals); | |
7daf5226 | 331 | |
e0fe7651 MW |
332 | return proposals; |
333 | } | |
7daf5226 | 334 | |
29e7fe63 TB |
335 | METHOD(ike_cfg_t, has_proposal, bool, |
336 | private_ike_cfg_t *this, proposal_t *match, bool private) | |
337 | { | |
338 | enumerator_t *enumerator; | |
339 | proposal_t *proposal; | |
340 | ||
341 | enumerator = this->proposals->create_enumerator(this->proposals); | |
342 | while (enumerator->enumerate(enumerator, &proposal)) | |
343 | { | |
f930b732 | 344 | if (proposal->matches(proposal, match, |
a2cb2c9c | 345 | private ? 0 : PROPOSAL_SKIP_PRIVATE)) |
29e7fe63 TB |
346 | { |
347 | enumerator->destroy(enumerator); | |
348 | return TRUE; | |
349 | } | |
350 | } | |
351 | enumerator->destroy(enumerator); | |
352 | return FALSE; | |
353 | } | |
354 | ||
deac3a0a | 355 | METHOD(ike_cfg_t, select_proposal, proposal_t*, |
f930b732 TE |
356 | private_ike_cfg_t *this, linked_list_t *proposals, |
357 | proposal_selection_flag_t flags) | |
e0fe7651 | 358 | { |
c9599d41 | 359 | return proposal_select(this->proposals, proposals, flags); |
e0fe7651 MW |
360 | } |
361 | ||
093fc1ac TB |
362 | METHOD(ike_cfg_t, get_algorithm, uint16_t, |
363 | private_ike_cfg_t *this, transform_type_t type) | |
e0fe7651 | 364 | { |
3c7e72f5 | 365 | enumerator_t *enumerator; |
e0fe7651 | 366 | proposal_t *proposal; |
093fc1ac | 367 | uint16_t alg = 0; |
7daf5226 | 368 | |
3c7e72f5 MW |
369 | enumerator = this->proposals->create_enumerator(this->proposals); |
370 | while (enumerator->enumerate(enumerator, &proposal)) | |
e0fe7651 | 371 | { |
093fc1ac | 372 | if (proposal->get_algorithm(proposal, type, &alg, NULL)) |
e0fe7651 | 373 | { |
e0fe7651 MW |
374 | break; |
375 | } | |
376 | } | |
3c7e72f5 | 377 | enumerator->destroy(enumerator); |
093fc1ac | 378 | return alg; |
e0fe7651 MW |
379 | } |
380 | ||
deac3a0a MW |
381 | METHOD(ike_cfg_t, equals, bool, |
382 | private_ike_cfg_t *this, ike_cfg_t *other_public) | |
3c7e72f5 | 383 | { |
deac3a0a | 384 | private_ike_cfg_t *other = (private_ike_cfg_t*)other_public; |
7daf5226 | 385 | |
3c7e72f5 MW |
386 | if (this == other) |
387 | { | |
388 | return TRUE; | |
389 | } | |
390 | if (this->public.equals != other->public.equals) | |
391 | { | |
392 | return FALSE; | |
393 | } | |
8db4f19a TB |
394 | if (!this->proposals->equals_offset(this->proposals, other->proposals, |
395 | offsetof(proposal_t, equals))) | |
3c7e72f5 MW |
396 | { |
397 | return FALSE; | |
398 | } | |
8db4f19a | 399 | return |
9fc7cc6f | 400 | this->version == other->version && |
3c7e72f5 | 401 | this->certreq == other->certreq && |
15612b3a | 402 | this->ocsp_certreq == other->ocsp_certreq && |
3c7e72f5 | 403 | this->force_encap == other->force_encap && |
97973f86 | 404 | this->fragmentation == other->fragmentation && |
ddb083c1 | 405 | this->childless == other->childless && |
5a22a021 | 406 | streq(this->me, other->me) && |
af2c43fd MW |
407 | streq(this->other, other->other) && |
408 | this->my_port == other->my_port && | |
8db4f19a | 409 | this->other_port == other->other_port; |
3c7e72f5 MW |
410 | } |
411 | ||
deac3a0a MW |
412 | METHOD(ike_cfg_t, get_ref, ike_cfg_t*, |
413 | private_ike_cfg_t *this) | |
e0fe7651 MW |
414 | { |
415 | ref_get(&this->refcount); | |
ff683671 | 416 | return &this->public; |
e0fe7651 MW |
417 | } |
418 | ||
deac3a0a MW |
419 | METHOD(ike_cfg_t, destroy, void, |
420 | private_ike_cfg_t *this) | |
e0fe7651 MW |
421 | { |
422 | if (ref_put(&this->refcount)) | |
423 | { | |
424 | this->proposals->destroy_offset(this->proposals, | |
425 | offsetof(proposal_t, destroy)); | |
5a22a021 MW |
426 | free(this->me); |
427 | free(this->other); | |
3070697f MW |
428 | this->my_hosts->destroy_function(this->my_hosts, free); |
429 | this->other_hosts->destroy_function(this->other_hosts, free); | |
430 | this->my_ranges->destroy_offset(this->my_ranges, | |
431 | offsetof(traffic_selector_t, destroy)); | |
432 | this->other_ranges->destroy_offset(this->other_ranges, | |
433 | offsetof(traffic_selector_t, destroy)); | |
e0fe7651 MW |
434 | free(this); |
435 | } | |
436 | } | |
437 | ||
3070697f MW |
438 | /** |
439 | * Try to parse a string as subnet | |
440 | */ | |
441 | static traffic_selector_t* make_subnet(char *str) | |
442 | { | |
443 | char *pos; | |
444 | ||
445 | pos = strchr(str, '/'); | |
446 | if (!pos) | |
447 | { | |
448 | return NULL; | |
449 | } | |
450 | return traffic_selector_create_from_cidr(str, 0, 0, 0); | |
451 | } | |
452 | ||
453 | /** | |
454 | * Try to parse a string as an IP range | |
455 | */ | |
456 | static traffic_selector_t* make_range(char *str) | |
457 | { | |
458 | traffic_selector_t *ts; | |
459 | ts_type_t type; | |
3070697f MW |
460 | host_t *from, *to; |
461 | ||
e0cd3bad | 462 | if (!host_create_from_range(str, &from, &to)) |
3070697f | 463 | { |
3070697f MW |
464 | return NULL; |
465 | } | |
466 | if (to->get_family(to) == AF_INET) | |
467 | { | |
468 | type = TS_IPV4_ADDR_RANGE; | |
469 | } | |
470 | else | |
471 | { | |
472 | type = TS_IPV6_ADDR_RANGE; | |
473 | } | |
474 | ts = traffic_selector_create_from_bytes(0, type, | |
475 | from->get_address(from), 0, | |
476 | to->get_address(to), 0); | |
477 | from->destroy(from); | |
478 | to->destroy(to); | |
479 | return ts; | |
480 | } | |
481 | ||
482 | /** | |
483 | * Parse address string into lists of single hosts and ranges/subnets | |
484 | */ | |
485 | static void parse_addresses(char *str, linked_list_t *hosts, | |
486 | linked_list_t *ranges) | |
487 | { | |
488 | enumerator_t *enumerator; | |
489 | traffic_selector_t *ts; | |
490 | ||
491 | enumerator = enumerator_create_token(str, ",", " "); | |
492 | while (enumerator->enumerate(enumerator, &str)) | |
493 | { | |
494 | ts = make_subnet(str); | |
495 | if (ts) | |
496 | { | |
497 | ranges->insert_last(ranges, ts); | |
498 | continue; | |
499 | } | |
500 | ts = make_range(str); | |
501 | if (ts) | |
502 | { | |
503 | ranges->insert_last(ranges, ts); | |
504 | continue; | |
505 | } | |
506 | hosts->insert_last(hosts, strdup(str)); | |
507 | } | |
508 | enumerator->destroy(enumerator); | |
509 | } | |
510 | ||
6bfa6606 TB |
511 | /** |
512 | * Described in header. | |
513 | */ | |
514 | int ike_cfg_get_family(ike_cfg_t *cfg, bool local) | |
515 | { | |
516 | private_ike_cfg_t *this = (private_ike_cfg_t*)cfg; | |
517 | enumerator_t *enumerator; | |
518 | host_t *host; | |
519 | char *str; | |
520 | int family = AF_UNSPEC; | |
521 | ||
522 | if (local) | |
523 | { | |
524 | enumerator = this->my_hosts->create_enumerator(this->my_hosts); | |
525 | } | |
526 | else | |
527 | { | |
528 | enumerator = this->other_hosts->create_enumerator(this->other_hosts); | |
529 | } | |
530 | while (enumerator->enumerate(enumerator, &str)) | |
531 | { | |
532 | if (streq(str, "%any")) | |
533 | { /* ignore %any as its family is undetermined */ | |
534 | continue; | |
535 | } | |
536 | host = host_create_from_string(str, 0); | |
537 | if (host) | |
538 | { | |
539 | if (family == AF_UNSPEC) | |
540 | { | |
541 | family = host->get_family(host); | |
542 | } | |
543 | else if (family != host->get_family(host)) | |
544 | { | |
545 | /* more than one address family defined */ | |
546 | family = AF_UNSPEC; | |
547 | host->destroy(host); | |
548 | break; | |
549 | } | |
550 | } | |
551 | DESTROY_IF(host); | |
552 | } | |
553 | enumerator->destroy(enumerator); | |
554 | return family; | |
555 | } | |
556 | ||
5a7a17b7 TB |
557 | /** |
558 | * Described in header. | |
559 | */ | |
560 | bool ike_cfg_has_address(ike_cfg_t *cfg, host_t *addr, bool local) | |
561 | { | |
562 | private_ike_cfg_t *this = (private_ike_cfg_t*)cfg; | |
563 | enumerator_t *enumerator; | |
564 | host_t *host; | |
565 | char *str; | |
566 | bool found = FALSE; | |
567 | ||
568 | if (local) | |
569 | { | |
570 | enumerator = this->my_hosts->create_enumerator(this->my_hosts); | |
571 | } | |
572 | else | |
573 | { | |
574 | enumerator = this->other_hosts->create_enumerator(this->other_hosts); | |
575 | } | |
576 | while (enumerator->enumerate(enumerator, &str)) | |
577 | { | |
578 | host = host_create_from_string(str, 0); | |
579 | if (host && addr->ip_equals(addr, host)) | |
580 | { | |
66805c7b | 581 | host->destroy(host); |
5a7a17b7 TB |
582 | found = TRUE; |
583 | break; | |
584 | } | |
585 | DESTROY_IF(host); | |
586 | } | |
587 | enumerator->destroy(enumerator); | |
588 | return found; | |
589 | } | |
590 | ||
9486a2e5 TB |
591 | /* |
592 | * Described in header | |
e0fe7651 | 593 | */ |
9486a2e5 | 594 | ike_cfg_t *ike_cfg_create(ike_cfg_create_t *data) |
e0fe7651 | 595 | { |
deac3a0a MW |
596 | private_ike_cfg_t *this; |
597 | ||
598 | INIT(this, | |
599 | .public = { | |
9fc7cc6f | 600 | .get_version = _get_version, |
deac3a0a | 601 | .send_certreq = _send_certreq, |
15612b3a | 602 | .send_ocsp_certreq = _send_ocsp_certreq, |
deac3a0a | 603 | .force_encap = _force_encap_, |
97973f86 | 604 | .fragmentation = _fragmentation, |
ddb083c1 | 605 | .childless = _childless, |
e743275c MW |
606 | .resolve_me = _resolve_me, |
607 | .resolve_other = _resolve_other, | |
6f666192 MW |
608 | .match_me = _match_me, |
609 | .match_other = _match_other, | |
deac3a0a MW |
610 | .get_my_addr = _get_my_addr, |
611 | .get_other_addr = _get_other_addr, | |
4e18490e MW |
612 | .get_my_port = _get_my_port, |
613 | .get_other_port = _get_other_port, | |
306a269e | 614 | .get_dscp = _get_dscp, |
deac3a0a MW |
615 | .add_proposal = _add_proposal, |
616 | .get_proposals = _get_proposals, | |
617 | .select_proposal = _select_proposal, | |
29e7fe63 | 618 | .has_proposal = _has_proposal, |
093fc1ac | 619 | .get_algorithm = _get_algorithm, |
deac3a0a MW |
620 | .equals = _equals, |
621 | .get_ref = _get_ref, | |
622 | .destroy = _destroy, | |
623 | }, | |
624 | .refcount = 1, | |
9486a2e5 TB |
625 | .version = data->version, |
626 | .certreq = !data->no_certreq, | |
9acd9057 | 627 | .ocsp_certreq = data->ocsp_certreq, |
9486a2e5 TB |
628 | .force_encap = data->force_encap, |
629 | .fragmentation = data->fragmentation, | |
ddb083c1 | 630 | .childless = data->childless, |
9486a2e5 | 631 | .me = strdup(data->local), |
3070697f MW |
632 | .my_ranges = linked_list_create(), |
633 | .my_hosts = linked_list_create(), | |
9486a2e5 | 634 | .other = strdup(data->remote), |
3070697f MW |
635 | .other_ranges = linked_list_create(), |
636 | .other_hosts = linked_list_create(), | |
9486a2e5 TB |
637 | .my_port = data->local_port, |
638 | .other_port = data->remote_port, | |
639 | .dscp = data->dscp, | |
deac3a0a MW |
640 | .proposals = linked_list_create(), |
641 | ); | |
7daf5226 | 642 | |
9486a2e5 TB |
643 | parse_addresses(data->local, this->my_hosts, this->my_ranges); |
644 | parse_addresses(data->remote, this->other_hosts, this->other_ranges); | |
3070697f | 645 | |
e0fe7651 MW |
646 | return &this->public; |
647 | } |