2 * Copyright (C) 2012-2019 Tobias Brunner
3 * Copyright (C) 2005-2007 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * HSR Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #define _GNU_SOURCE /* for stdndup() */
25 ENUM(ike_version_names
, IKE_ANY
, IKEV2
,
31 typedef struct private_ike_cfg_t private_ike_cfg_t
;
34 * Private data of an ike_cfg_t object
36 struct private_ike_cfg_t
{
44 * Number of references hold by others to this ike_cfg
51 ike_version_t version
;
54 * Address list string for local host
59 * Address list string for remote host
64 * Local single host or DNS names, as allocated char*
66 linked_list_t
*my_hosts
;
69 * Remote single host or DNS names, as allocated char*
71 linked_list_t
*other_hosts
;
74 * Local ranges/subnets this config matches to, as traffic_selector_t*
76 linked_list_t
*my_ranges
;
79 * Remote ranges/subnets this config matches to, as traffic_selector_t*
81 linked_list_t
*other_ranges
;
94 * should we send a certificate request?
99 * enforce UDP encapsulation
104 * use IKE fragmentation
106 fragmentation_t fragmentation
;
111 childless_t childless
;
114 * DSCP value to use on sent IKE packets
119 * List of proposals to use
121 linked_list_t
*proposals
;
124 METHOD(ike_cfg_t
, get_version
, ike_version_t
,
125 private_ike_cfg_t
*this)
127 return this->version
;
130 METHOD(ike_cfg_t
, send_certreq
, bool,
131 private_ike_cfg_t
*this)
133 return this->certreq
;
136 METHOD(ike_cfg_t
, force_encap_
, bool,
137 private_ike_cfg_t
*this)
139 return this->force_encap
;
142 METHOD(ike_cfg_t
, fragmentation
, fragmentation_t
,
143 private_ike_cfg_t
*this)
145 return this->fragmentation
;
148 METHOD(ike_cfg_t
, childless
, childless_t
,
149 private_ike_cfg_t
*this)
151 return this->childless
;
155 * Common function for resolve_me/other
157 static host_t
* resolve(linked_list_t
*hosts
, int family
, uint16_t port
)
159 enumerator_t
*enumerator
;
164 enumerator
= hosts
->create_enumerator(hosts
);
165 while (enumerator
->enumerate(enumerator
, &str
))
167 host
= host_create_from_dns(str
, family
, port
);
174 enumerator
->destroy(enumerator
);
178 /* we have no single host configured, return %any */
179 host
= host_create_any(family ?
: AF_INET
);
180 host
->set_port(host
, port
);
185 METHOD(ike_cfg_t
, resolve_me
, host_t
*,
186 private_ike_cfg_t
*this, int family
)
188 return resolve(this->my_hosts
, family
, this->my_port
);
191 METHOD(ike_cfg_t
, resolve_other
, host_t
*,
192 private_ike_cfg_t
*this, int family
)
194 return resolve(this->other_hosts
, family
, this->other_port
);
198 * Common function for match_me/other
200 static u_int
match(linked_list_t
*hosts
, linked_list_t
*ranges
, host_t
*cand
)
202 enumerator_t
*enumerator
;
203 traffic_selector_t
*ts
;
209 /* try single hosts first */
210 enumerator
= hosts
->create_enumerator(hosts
);
211 while (enumerator
->enumerate(enumerator
, &str
))
213 host
= host_create_from_dns(str
, cand
->get_family(cand
), 0);
216 if (host
->ip_equals(host
, cand
))
218 quality
= max(quality
, 128 + 1);
220 if (host
->is_anyaddr(host
))
222 quality
= max(quality
, 1);
227 enumerator
->destroy(enumerator
);
229 /* then ranges/subnets */
230 enumerator
= ranges
->create_enumerator(ranges
);
231 while (enumerator
->enumerate(enumerator
, &ts
))
233 if (ts
->includes(ts
, cand
))
235 if (ts
->to_subnet(ts
, &host
, &mask
))
237 quality
= max(quality
, mask
+ 1);
241 quality
= max(quality
, 1);
246 enumerator
->destroy(enumerator
);
251 METHOD(ike_cfg_t
, match_me
, u_int
,
252 private_ike_cfg_t
*this, host_t
*host
)
254 return match(this->my_hosts
, this->my_ranges
, host
);
257 METHOD(ike_cfg_t
, match_other
, u_int
,
258 private_ike_cfg_t
*this, host_t
*host
)
260 return match(this->other_hosts
, this->other_ranges
, host
);
263 METHOD(ike_cfg_t
, get_my_addr
, char*,
264 private_ike_cfg_t
*this)
269 METHOD(ike_cfg_t
, get_other_addr
, char*,
270 private_ike_cfg_t
*this)
275 METHOD(ike_cfg_t
, get_my_port
, uint16_t,
276 private_ike_cfg_t
*this)
278 return this->my_port
;
281 METHOD(ike_cfg_t
, get_other_port
, uint16_t,
282 private_ike_cfg_t
*this)
284 return this->other_port
;
287 METHOD(ike_cfg_t
, get_dscp
, uint8_t,
288 private_ike_cfg_t
*this)
293 METHOD(ike_cfg_t
, add_proposal
, void,
294 private_ike_cfg_t
*this, proposal_t
*proposal
)
298 this->proposals
->insert_last(this->proposals
, proposal
);
302 METHOD(ike_cfg_t
, get_proposals
, linked_list_t
*,
303 private_ike_cfg_t
*this)
305 enumerator_t
*enumerator
;
307 linked_list_t
*proposals
;
309 proposals
= linked_list_create();
310 enumerator
= this->proposals
->create_enumerator(this->proposals
);
311 while (enumerator
->enumerate(enumerator
, ¤t
))
313 current
= current
->clone(current
);
314 proposals
->insert_last(proposals
, current
);
316 enumerator
->destroy(enumerator
);
318 DBG2(DBG_CFG
, "configured proposals: %#P", proposals
);
323 METHOD(ike_cfg_t
, has_proposal
, bool,
324 private_ike_cfg_t
*this, proposal_t
*match
, bool private)
326 enumerator_t
*enumerator
;
327 proposal_t
*proposal
;
329 enumerator
= this->proposals
->create_enumerator(this->proposals
);
330 while (enumerator
->enumerate(enumerator
, &proposal
))
332 if (proposal
->matches(proposal
, match
,
333 private ? PROPOSAL_ALLOW_PRIVATE
: 0))
335 enumerator
->destroy(enumerator
);
339 enumerator
->destroy(enumerator
);
343 METHOD(ike_cfg_t
, select_proposal
, proposal_t
*,
344 private_ike_cfg_t
*this, linked_list_t
*proposals
,
345 proposal_selection_flag_t flags
)
347 return proposal_select(this->proposals
, proposals
, flags
);
350 METHOD(ike_cfg_t
, get_dh_group
, diffie_hellman_group_t
,
351 private_ike_cfg_t
*this)
353 enumerator_t
*enumerator
;
354 proposal_t
*proposal
;
355 uint16_t dh_group
= MODP_NONE
;
357 enumerator
= this->proposals
->create_enumerator(this->proposals
);
358 while (enumerator
->enumerate(enumerator
, &proposal
))
360 if (proposal
->get_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
, &dh_group
, NULL
))
365 enumerator
->destroy(enumerator
);
369 METHOD(ike_cfg_t
, equals
, bool,
370 private_ike_cfg_t
*this, ike_cfg_t
*other_public
)
372 private_ike_cfg_t
*other
= (private_ike_cfg_t
*)other_public
;
378 if (this->public.equals
!= other
->public.equals
)
382 if (!this->proposals
->equals_offset(this->proposals
, other
->proposals
,
383 offsetof(proposal_t
, equals
)))
388 this->version
== other
->version
&&
389 this->certreq
== other
->certreq
&&
390 this->force_encap
== other
->force_encap
&&
391 this->fragmentation
== other
->fragmentation
&&
392 this->childless
== other
->childless
&&
393 streq(this->me
, other
->me
) &&
394 streq(this->other
, other
->other
) &&
395 this->my_port
== other
->my_port
&&
396 this->other_port
== other
->other_port
;
399 METHOD(ike_cfg_t
, get_ref
, ike_cfg_t
*,
400 private_ike_cfg_t
*this)
402 ref_get(&this->refcount
);
403 return &this->public;
406 METHOD(ike_cfg_t
, destroy
, void,
407 private_ike_cfg_t
*this)
409 if (ref_put(&this->refcount
))
411 this->proposals
->destroy_offset(this->proposals
,
412 offsetof(proposal_t
, destroy
));
415 this->my_hosts
->destroy_function(this->my_hosts
, free
);
416 this->other_hosts
->destroy_function(this->other_hosts
, free
);
417 this->my_ranges
->destroy_offset(this->my_ranges
,
418 offsetof(traffic_selector_t
, destroy
));
419 this->other_ranges
->destroy_offset(this->other_ranges
,
420 offsetof(traffic_selector_t
, destroy
));
426 * Try to parse a string as subnet
428 static traffic_selector_t
* make_subnet(char *str
)
432 pos
= strchr(str
, '/');
437 return traffic_selector_create_from_cidr(str
, 0, 0, 0);
441 * Try to parse a string as an IP range
443 static traffic_selector_t
* make_range(char *str
)
445 traffic_selector_t
*ts
;
449 if (!host_create_from_range(str
, &from
, &to
))
453 if (to
->get_family(to
) == AF_INET
)
455 type
= TS_IPV4_ADDR_RANGE
;
459 type
= TS_IPV6_ADDR_RANGE
;
461 ts
= traffic_selector_create_from_bytes(0, type
,
462 from
->get_address(from
), 0,
463 to
->get_address(to
), 0);
470 * Parse address string into lists of single hosts and ranges/subnets
472 static void parse_addresses(char *str
, linked_list_t
*hosts
,
473 linked_list_t
*ranges
)
475 enumerator_t
*enumerator
;
476 traffic_selector_t
*ts
;
478 enumerator
= enumerator_create_token(str
, ",", " ");
479 while (enumerator
->enumerate(enumerator
, &str
))
481 ts
= make_subnet(str
);
484 ranges
->insert_last(ranges
, ts
);
487 ts
= make_range(str
);
490 ranges
->insert_last(ranges
, ts
);
493 hosts
->insert_last(hosts
, strdup(str
));
495 enumerator
->destroy(enumerator
);
499 * Described in header.
501 int ike_cfg_get_family(ike_cfg_t
*cfg
, bool local
)
503 private_ike_cfg_t
*this = (private_ike_cfg_t
*)cfg
;
504 enumerator_t
*enumerator
;
507 int family
= AF_UNSPEC
;
511 enumerator
= this->my_hosts
->create_enumerator(this->my_hosts
);
515 enumerator
= this->other_hosts
->create_enumerator(this->other_hosts
);
517 while (enumerator
->enumerate(enumerator
, &str
))
519 if (streq(str
, "%any"))
520 { /* ignore %any as its family is undetermined */
523 host
= host_create_from_string(str
, 0);
526 if (family
== AF_UNSPEC
)
528 family
= host
->get_family(host
);
530 else if (family
!= host
->get_family(host
))
532 /* more than one address family defined */
540 enumerator
->destroy(enumerator
);
545 * Described in header.
547 bool ike_cfg_has_address(ike_cfg_t
*cfg
, host_t
*addr
, bool local
)
549 private_ike_cfg_t
*this = (private_ike_cfg_t
*)cfg
;
550 enumerator_t
*enumerator
;
557 enumerator
= this->my_hosts
->create_enumerator(this->my_hosts
);
561 enumerator
= this->other_hosts
->create_enumerator(this->other_hosts
);
563 while (enumerator
->enumerate(enumerator
, &str
))
565 host
= host_create_from_string(str
, 0);
566 if (host
&& addr
->ip_equals(addr
, host
))
574 enumerator
->destroy(enumerator
);
579 * Described in header
581 ike_cfg_t
*ike_cfg_create(ike_cfg_create_t
*data
)
583 private_ike_cfg_t
*this;
587 .get_version
= _get_version
,
588 .send_certreq
= _send_certreq
,
589 .force_encap
= _force_encap_
,
590 .fragmentation
= _fragmentation
,
591 .childless
= _childless
,
592 .resolve_me
= _resolve_me
,
593 .resolve_other
= _resolve_other
,
594 .match_me
= _match_me
,
595 .match_other
= _match_other
,
596 .get_my_addr
= _get_my_addr
,
597 .get_other_addr
= _get_other_addr
,
598 .get_my_port
= _get_my_port
,
599 .get_other_port
= _get_other_port
,
600 .get_dscp
= _get_dscp
,
601 .add_proposal
= _add_proposal
,
602 .get_proposals
= _get_proposals
,
603 .select_proposal
= _select_proposal
,
604 .has_proposal
= _has_proposal
,
605 .get_dh_group
= _get_dh_group
,
611 .version
= data
->version
,
612 .certreq
= !data
->no_certreq
,
613 .force_encap
= data
->force_encap
,
614 .fragmentation
= data
->fragmentation
,
615 .childless
= data
->childless
,
616 .me
= strdup(data
->local
),
617 .my_ranges
= linked_list_create(),
618 .my_hosts
= linked_list_create(),
619 .other
= strdup(data
->remote
),
620 .other_ranges
= linked_list_create(),
621 .other_hosts
= linked_list_create(),
622 .my_port
= data
->local_port
,
623 .other_port
= data
->remote_port
,
625 .proposals
= linked_list_create(),
628 parse_addresses(data
->local
, this->my_hosts
, this->my_ranges
);
629 parse_addresses(data
->remote
, this->other_hosts
, this->other_ranges
);
631 return &this->public;