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