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