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