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