fixed CHILD_SA proposal selection when not using DH exchange
[strongswan.git] / src / charon / config / traffic_selector.c
1 /**
2 * @file traffic_selector.c
3 *
4 * @brief Implementation of traffic_selector_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2007 Tobias Brunner
10 * Copyright (C) 2005-2007 Martin Willi
11 * Copyright (C) 2005 Jan Hutter
12 * Hochschule fuer Technik Rapperswil
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 */
24
25 #include <arpa/inet.h>
26 #include <string.h>
27 #include <netdb.h>
28 #include <stdio.h>
29 #include <printf.h>
30
31 #include "traffic_selector.h"
32
33 #include <daemon.h>
34 #include <utils/linked_list.h>
35 #include <utils/identification.h>
36
37 ENUM(ts_type_name, TS_IPV4_ADDR_RANGE, TS_IPV6_ADDR_RANGE,
38 "TS_IPV4_ADDR_RANGE",
39 "TS_IPV6_ADDR_RANGE",
40 );
41
42 typedef struct private_traffic_selector_t private_traffic_selector_t;
43
44 /**
45 * Private data of an traffic_selector_t object
46 */
47 struct private_traffic_selector_t {
48
49 /**
50 * Public part
51 */
52 traffic_selector_t public;
53
54 /**
55 * Type of address
56 */
57 ts_type_t type;
58
59 /**
60 * IP protocol (UDP, TCP, ICMP, ...)
61 */
62 u_int8_t protocol;
63
64 /**
65 * narrow this traffic selector to hosts external ip
66 * if set, from and to have no meaning until set_address() is called
67 */
68 bool dynamic;
69
70 /**
71 * begin of address range, network order
72 */
73 union {
74 /** dummy char for common address manipulation */
75 char from[0];
76 /** IPv4 address */
77 u_int32_t from4[1];
78 /** IPv6 address */
79 u_int32_t from6[4];
80 };
81
82 /**
83 * end of address range, network order
84 */
85 union {
86 /** dummy char for common address manipulation */
87 char to[0];
88 /** IPv4 address */
89 u_int32_t to4[1];
90 /** IPv6 address */
91 u_int32_t to6[4];
92 };
93
94 /**
95 * begin of port range
96 */
97 u_int16_t from_port;
98
99 /**
100 * end of port range
101 */
102 u_int16_t to_port;
103 };
104
105 /**
106 * calculate to "to"-address for the "from" address and a subnet size
107 */
108 static void calc_range(private_traffic_selector_t *this, u_int8_t netbits)
109 {
110 int byte;
111 size_t size = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
112
113 /* go through the from address, starting at the tail. While we
114 * have not processed the bits belonging to the host, set them to 1 on
115 * the to address. If we reach the bits for the net, copy them from "from". */
116 for (byte = size - 1; byte >=0; byte--)
117 {
118 u_char mask = 0x00;
119 int shift;
120
121 shift = (byte+1) * 8 - netbits;
122 if (shift > 0)
123 {
124 mask = 1 << shift;
125 if (mask != 0xFF)
126 {
127 mask--;
128 }
129 }
130 this->to[byte] = this->from[byte] | mask;
131 }
132 }
133
134 /**
135 * calculate to subnet size from "to"- and "from"-address
136 */
137 static u_int8_t calc_netbits(private_traffic_selector_t *this)
138 {
139 int byte, bit;
140 size_t size = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
141
142 /* go trough all bits of the addresses, begging in the front.
143 * As longer as they equal, the subnet gets larger */
144 for (byte = 0; byte < size; byte++)
145 {
146 for (bit = 7; bit >= 0; bit--)
147 {
148 if ((1<<bit & this->from[byte]) != (1<<bit & this->to[byte]))
149 {
150 return ((7 - bit) + (byte * 8));
151 }
152 }
153 }
154 /* single host, netmask is 32/128 */
155 return (size * 8);
156 }
157
158 /**
159 * internal generic constructor
160 */
161 static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts_type_t type, u_int16_t from_port, u_int16_t to_port);
162
163 /**
164 * output handler in printf()
165 */
166 static int print(FILE *stream, const struct printf_info *info,
167 const void *const *args)
168 {
169 private_traffic_selector_t *this = *((private_traffic_selector_t**)(args[0]));
170 linked_list_t *list = *((linked_list_t**)(args[0]));
171 iterator_t *iterator;
172 char addr_str[INET6_ADDRSTRLEN] = "";
173 char *serv_proto = NULL;
174 u_int8_t mask;
175 bool has_proto;
176 bool has_ports;
177 size_t written = 0;
178
179 if (this == NULL)
180 {
181 return fprintf(stream, "(null)");
182 }
183
184 if (info->alt)
185 {
186 iterator = list->create_iterator(list, TRUE);
187 while (iterator->iterate(iterator, (void**)&this))
188 {
189 /* call recursivly */
190 written += fprintf(stream, "%R ", this);
191 }
192 iterator->destroy(iterator);
193 return written;
194 }
195
196 if (this->dynamic)
197 {
198 return fprintf(stream, "dynamic/%d",
199 this->type == TS_IPV4_ADDR_RANGE ? 32 : 128);
200 }
201
202 if (this->type == TS_IPV4_ADDR_RANGE)
203 {
204 inet_ntop(AF_INET, &this->from4, addr_str, sizeof(addr_str));
205 }
206 else
207 {
208 inet_ntop(AF_INET6, &this->from6, addr_str, sizeof(addr_str));
209 }
210 mask = calc_netbits(this);
211
212 written += fprintf(stream, "%s/%d", addr_str, mask);
213
214 /* check if we have protocol and/or port selectors */
215 has_proto = this->protocol != 0;
216 has_ports = !(this->from_port == 0 && this->to_port == 0xFFFF);
217
218 if (!has_proto && !has_ports)
219 {
220 return written;
221 }
222
223 written += fprintf(stream, "[");
224
225 /* build protocol string */
226 if (has_proto)
227 {
228 struct protoent *proto = getprotobynumber(this->protocol);
229
230 if (proto)
231 {
232 written += fprintf(stream, "%s", proto->p_name);
233 serv_proto = proto->p_name;
234 }
235 else
236 {
237 written += fprintf(stream, "%d", this->protocol);
238 }
239 }
240
241 if (has_proto && has_ports)
242 {
243 written += fprintf(stream, "/");
244 }
245
246 /* build port string */
247 if (has_ports)
248 {
249 if (this->from_port == this->to_port)
250 {
251 struct servent *serv = getservbyport(htons(this->from_port), serv_proto);
252
253 if (serv)
254 {
255 written += fprintf(stream, "%s", serv->s_name);
256 }
257 else
258 {
259 written += fprintf(stream, "%d", this->from_port);
260 }
261 }
262 else
263 {
264 written += fprintf(stream, "%d-%d", this->from_port, this->to_port);
265 }
266 }
267
268 written += fprintf(stream, "]");
269
270 return written;
271 }
272
273 /**
274 * register printf() handlers
275 */
276 static void __attribute__ ((constructor))print_register()
277 {
278 register_printf_function(PRINTF_TRAFFIC_SELECTOR, print, arginfo_ptr);
279 }
280
281 /**
282 * implements traffic_selector_t.get_subset
283 */
284 static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_traffic_selector_t *other)
285 {
286 if (this->type == other->type && (this->protocol == other->protocol ||
287 this->protocol == 0 || other->protocol == 0))
288 {
289 u_int16_t from_port, to_port;
290 u_char *from, *to;
291 u_int8_t protocol;
292 size_t size;
293 private_traffic_selector_t *new_ts;
294
295 /* calculate the maximum port range allowed for both */
296 from_port = max(this->from_port, other->from_port);
297 to_port = min(this->to_port, other->to_port);
298 if (from_port > to_port)
299 {
300 return NULL;
301 }
302 /* select protocol, which is not zero */
303 protocol = max(this->protocol, other->protocol);
304
305 switch (this->type)
306 {
307 case TS_IPV4_ADDR_RANGE:
308 size = sizeof(this->from4);
309 break;
310 case TS_IPV6_ADDR_RANGE:
311 size = sizeof(this->from6);
312 break;
313 default:
314 return NULL;
315 }
316
317 /* get higher from-address */
318 if (memcmp(this->from, other->from, size) > 0)
319 {
320 from = this->from;
321 }
322 else
323 {
324 from = other->from;
325 }
326 /* get lower to-address */
327 if (memcmp(this->to, other->to, size) > 0)
328 {
329 to = other->to;
330 }
331 else
332 {
333 to = this->to;
334 }
335 /* if "from" > "to", we don't have a match */
336 if (memcmp(from, to, size) > 0)
337 {
338 return NULL;
339 }
340
341 /* we have a match in protocol, port, and address: return it... */
342 new_ts = traffic_selector_create(protocol, this->type, from_port, to_port);
343 new_ts->type = this->type;
344 memcpy(new_ts->from, from, size);
345 memcpy(new_ts->to, to, size);
346
347 return &new_ts->public;
348 }
349 return NULL;
350 }
351
352 /**
353 * implements traffic_selector_t.equals
354 */
355 static bool equals(private_traffic_selector_t *this, private_traffic_selector_t *other)
356 {
357 if (this->type != other->type)
358 {
359 return FALSE;
360 }
361 if (!(this->from_port == other->from_port &&
362 this->to_port == other->to_port &&
363 this->protocol == other->protocol))
364 {
365 return FALSE;
366 }
367 switch (this->type)
368 {
369 case TS_IPV4_ADDR_RANGE:
370 if (memeq(this->from4, other->from4, sizeof(this->from4)))
371 {
372 return TRUE;
373 }
374 break;
375 case TS_IPV6_ADDR_RANGE:
376 if (memeq(this->from6, other->from6, sizeof(this->from6)))
377 {
378 return TRUE;
379 }
380 break;
381 default:
382 break;
383 }
384 return FALSE;
385 }
386
387 /**
388 * Implements traffic_selector_t.get_from_address.
389 */
390 static chunk_t get_from_address(private_traffic_selector_t *this)
391 {
392 chunk_t from = chunk_empty;
393
394 switch (this->type)
395 {
396 case TS_IPV4_ADDR_RANGE:
397 {
398 from.len = sizeof(this->from4);
399 from.ptr = malloc(from.len);
400 memcpy(from.ptr, this->from4, from.len);
401 break;
402 }
403 case TS_IPV6_ADDR_RANGE:
404 {
405 from.len = sizeof(this->from6);
406 from.ptr = malloc(from.len);
407 memcpy(from.ptr, this->from6, from.len);
408 break;
409 }
410 }
411 return from;
412 }
413
414 /**
415 * Implements traffic_selector_t.get_to_address.
416 */
417 static chunk_t get_to_address(private_traffic_selector_t *this)
418 {
419 chunk_t to = chunk_empty;
420
421 switch (this->type)
422 {
423 case TS_IPV4_ADDR_RANGE:
424 {
425 to.len = sizeof(this->to4);
426 to.ptr = malloc(to.len);
427 memcpy(to.ptr, this->to4, to.len);
428 break;
429 }
430 case TS_IPV6_ADDR_RANGE:
431 {
432 to.len = sizeof(this->to6);
433 to.ptr = malloc(to.len);
434 memcpy(to.ptr, this->to6, to.len);
435 break;
436 }
437 }
438 return to;
439 }
440
441 /**
442 * Implements traffic_selector_t.get_from_port.
443 */
444 static u_int16_t get_from_port(private_traffic_selector_t *this)
445 {
446 return this->from_port;
447 }
448
449 /**
450 * Implements traffic_selector_t.get_to_port.
451 */
452 static u_int16_t get_to_port(private_traffic_selector_t *this)
453 {
454 return this->to_port;
455 }
456
457 /**
458 * Implements traffic_selector_t.get_type.
459 */
460 static ts_type_t get_type(private_traffic_selector_t *this)
461 {
462 return this->type;
463 }
464
465 /**
466 * Implements traffic_selector_t.get_protocol.
467 */
468 static u_int8_t get_protocol(private_traffic_selector_t *this)
469 {
470 return this->protocol;
471 }
472
473 /**
474 * Implements traffic_selector_t.is_host.
475 */
476 static bool is_host(private_traffic_selector_t *this, host_t *host)
477 {
478 if (this->dynamic)
479 {
480 return TRUE;
481 }
482
483 if (host)
484 {
485 chunk_t addr;
486 int family = host->get_family(host);
487
488 if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
489 (family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
490 {
491 addr = host->get_address(host);
492 if (memeq(addr.ptr, this->from, addr.len) &&
493 memeq(addr.ptr, this->to, addr.len))
494 {
495 return TRUE;
496 }
497 }
498 }
499 else
500 {
501 size_t length = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
502
503 if (memeq(this->from, this->to, length))
504 {
505 return TRUE;
506 }
507 }
508 return FALSE;
509 }
510
511 /**
512 * Implements traffic_selector_t.set_address.
513 */
514 static void set_address(private_traffic_selector_t *this, host_t *host)
515 {
516 if (this->dynamic)
517 {
518 this->type = host->get_family(host) == AF_INET ?
519 TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE;
520
521 chunk_t from = host->get_address(host);
522 memcpy(this->from, from.ptr, from.len);
523 memcpy(this->to, from.ptr, from.len);
524 }
525 }
526
527 /**
528 * Implements traffic_selector_t.is_contained_in.
529 */
530 static bool is_contained_in(private_traffic_selector_t *this,
531 private_traffic_selector_t *other)
532 {
533 private_traffic_selector_t *subset;
534 bool contained_in = FALSE;
535
536 subset = (private_traffic_selector_t*)get_subset(this, other);
537
538 if (subset)
539 {
540 if (equals(subset, this))
541 {
542 contained_in = TRUE;
543 }
544 free(subset);
545 }
546 return contained_in;
547 }
548
549 /**
550 * Implements traffic_selector_t.includes.
551 */
552 static bool includes(private_traffic_selector_t *this, host_t *host)
553 {
554 chunk_t addr;
555 int family = host->get_family(host);
556
557 if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
558 (family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
559 {
560 addr = host->get_address(host);
561
562 return memcmp(this->from, addr.ptr, addr.len) <= 0 &&
563 memcmp(this->to, addr.ptr, addr.len) >= 0;
564 }
565
566 return FALSE;
567 }
568
569 /**
570 * Implements traffic_selector_t.clone.
571 */
572 static traffic_selector_t *clone_(private_traffic_selector_t *this)
573 {
574 private_traffic_selector_t *clone;
575
576 clone = traffic_selector_create(this->protocol, this->type,
577 this->from_port, this->to_port);
578
579 clone->dynamic = this->dynamic;
580 switch (clone->type)
581 {
582 case TS_IPV4_ADDR_RANGE:
583 {
584 memcpy(clone->from4, this->from4, sizeof(this->from4));
585 memcpy(clone->to4, this->to4, sizeof(this->to4));
586 return &clone->public;
587 }
588 case TS_IPV6_ADDR_RANGE:
589 {
590 memcpy(clone->from6, this->from6, sizeof(this->from6));
591 memcpy(clone->to6, this->to6, sizeof(this->to6));
592 return &clone->public;
593 }
594 default:
595 {
596 /* unreachable */
597 return &clone->public;
598 }
599 }
600 }
601
602 /**
603 * Implements traffic_selector_t.destroy.
604 */
605 static void destroy(private_traffic_selector_t *this)
606 {
607 free(this);
608 }
609
610 /*
611 * see header
612 */
613 traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol,
614 ts_type_t type,
615 chunk_t from, u_int16_t from_port,
616 chunk_t to, u_int16_t to_port)
617 {
618 private_traffic_selector_t *this = traffic_selector_create(protocol, type,
619 from_port, to_port);
620
621 switch (type)
622 {
623 case TS_IPV4_ADDR_RANGE:
624 {
625 if (from.len != 4 || to.len != 4)
626 {
627 free(this);
628 return NULL;
629 }
630 memcpy(this->from4, from.ptr, from.len);
631 memcpy(this->to4, to.ptr, to.len);
632 break;
633 }
634 case TS_IPV6_ADDR_RANGE:
635 {
636 if (from.len != 16 || to.len != 16)
637 {
638 free(this);
639 return NULL;
640 }
641 memcpy(this->from6, from.ptr, from.len);
642 memcpy(this->to6, to.ptr, to.len);
643 break;
644 }
645 default:
646 {
647 free(this);
648 return NULL;
649 }
650 }
651 return (&this->public);
652 }
653
654 /*
655 * see header
656 */
657 traffic_selector_t *traffic_selector_create_from_subnet(host_t *net,
658 u_int8_t netbits, u_int8_t protocol, u_int16_t port)
659 {
660 private_traffic_selector_t *this = traffic_selector_create(protocol, 0, 0, 65535);
661
662 switch (net->get_family(net))
663 {
664 case AF_INET:
665 {
666 chunk_t from;
667
668 this->type = TS_IPV4_ADDR_RANGE;
669 from = net->get_address(net);
670 memcpy(this->from4, from.ptr, from.len);
671 if (this->from4[0] == 0)
672 {
673 /* use /0 for 0.0.0.0 */
674 this->to4[0] = ~0;
675 }
676 else
677 {
678 calc_range(this, netbits);
679 }
680 break;
681 }
682 case AF_INET6:
683 {
684 chunk_t from;
685
686 this->type = TS_IPV6_ADDR_RANGE;
687 from = net->get_address(net);
688 memcpy(this->from6, from.ptr, from.len);
689 if (this->from6[0] == 0 && this->from6[1] == 0 &&
690 this->from6[2] == 0 && this->from6[3] == 0)
691 {
692 /* use /0 for ::0 */
693 this->to6[0] = ~0;
694 this->to6[1] = ~0;
695 this->to6[2] = ~0;
696 this->to6[3] = ~0;
697 }
698 else
699 {
700 calc_range(this, netbits);
701 }
702 break;
703 }
704 default:
705 {
706 free(this);
707 return NULL;
708 }
709 }
710 if (port)
711 {
712 this->from_port = port;
713 this->to_port = port;
714 }
715 return (&this->public);
716 }
717
718 /*
719 * see header
720 */
721 traffic_selector_t *traffic_selector_create_from_string(
722 u_int8_t protocol, ts_type_t type,
723 char *from_addr, u_int16_t from_port,
724 char *to_addr, u_int16_t to_port)
725 {
726 private_traffic_selector_t *this = traffic_selector_create(protocol, type,
727 from_port, to_port);
728
729 this->type = type;
730 switch (type)
731 {
732 case TS_IPV4_ADDR_RANGE:
733 {
734 if (inet_pton(AF_INET, from_addr, (struct in_addr*)this->from4) < 0)
735 {
736 free(this);
737 return NULL;
738 }
739 if (inet_pton(AF_INET, to_addr, (struct in_addr*)this->to4) < 0)
740 {
741 free(this);
742 return NULL;
743 }
744 break;
745 }
746 case TS_IPV6_ADDR_RANGE:
747 {
748 if (inet_pton(AF_INET6, from_addr, (struct in6_addr*)this->from6) < 0)
749 {
750 free(this);
751 return NULL;
752 }
753 if (inet_pton(AF_INET6, to_addr, (struct in6_addr*)this->to6) < 0)
754 {
755 free(this);
756 return NULL;
757 }
758 break;
759 }
760 }
761 return (&this->public);
762 }
763
764 /*
765 * see header
766 */
767 traffic_selector_t *traffic_selector_create_dynamic(
768 u_int8_t protocol, ts_type_t type,
769 u_int16_t from_port, u_int16_t to_port)
770 {
771 private_traffic_selector_t *this = traffic_selector_create(protocol, type,
772 from_port, to_port);
773
774 memset(this->from6, 0, sizeof(this->from6));
775 memset(this->to6, 0xFF, sizeof(this->to6));
776
777 this->dynamic = TRUE;
778
779 return &this->public;
780 }
781
782 /*
783 * see declaration
784 */
785 static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol,
786 ts_type_t type, u_int16_t from_port, u_int16_t to_port)
787 {
788 private_traffic_selector_t *this = malloc_thing(private_traffic_selector_t);
789
790 /* public functions */
791 this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset;
792 this->public.equals = (bool(*)(traffic_selector_t*,traffic_selector_t*))equals;
793 this->public.get_from_address = (chunk_t(*)(traffic_selector_t*))get_from_address;
794 this->public.get_to_address = (chunk_t(*)(traffic_selector_t*))get_to_address;
795 this->public.get_from_port = (u_int16_t(*)(traffic_selector_t*))get_from_port;
796 this->public.get_to_port = (u_int16_t(*)(traffic_selector_t*))get_to_port;
797 this->public.get_type = (ts_type_t(*)(traffic_selector_t*))get_type;
798 this->public.get_protocol = (u_int8_t(*)(traffic_selector_t*))get_protocol;
799 this->public.is_host = (bool(*)(traffic_selector_t*,host_t*))is_host;
800 this->public.is_contained_in = (bool(*)(traffic_selector_t*,traffic_selector_t*))is_contained_in;
801 this->public.includes = (bool(*)(traffic_selector_t*,host_t*))includes;
802 this->public.set_address = (void(*)(traffic_selector_t*,host_t*))set_address;
803 this->public.clone = (traffic_selector_t*(*)(traffic_selector_t*))clone_;
804 this->public.destroy = (void(*)(traffic_selector_t*))destroy;
805
806 this->from_port = from_port;
807 this->to_port = to_port;
808 this->protocol = protocol;
809 this->type = type;
810 this->dynamic = FALSE;
811
812 return this;
813 }
814
815 /* vim: set ts=4 sw=4 noet: */