show kind of notify contained in messages in log
[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 u_int32_t from[4], to[4];
179
180 if (this == NULL)
181 {
182 return fprintf(stream, "(null)");
183 }
184
185 if (info->alt)
186 {
187 iterator = list->create_iterator(list, TRUE);
188 while (iterator->iterate(iterator, (void**)&this))
189 {
190 /* call recursivly */
191 written += fprintf(stream, "%R ", this);
192 }
193 iterator->destroy(iterator);
194 return written;
195 }
196
197 memset(from, 0, sizeof(from));
198 memset(to, 0xFF, sizeof(to));
199 if (this->dynamic &&
200 memeq(this->from, from, this->type == TS_IPV4_ADDR_RANGE ? 4 : 16) &&
201 memeq(this->to, to, this->type == TS_IPV4_ADDR_RANGE ? 4 : 16))
202 {
203 return fprintf(stream, "dynamic/%d",
204 this->type == TS_IPV4_ADDR_RANGE ? 32 : 128);
205 }
206
207 if (this->type == TS_IPV4_ADDR_RANGE)
208 {
209 inet_ntop(AF_INET, &this->from4, addr_str, sizeof(addr_str));
210 }
211 else
212 {
213 inet_ntop(AF_INET6, &this->from6, addr_str, sizeof(addr_str));
214 }
215 mask = calc_netbits(this);
216
217 written += fprintf(stream, "%s/%d", addr_str, mask);
218
219 /* check if we have protocol and/or port selectors */
220 has_proto = this->protocol != 0;
221 has_ports = !(this->from_port == 0 && this->to_port == 0xFFFF);
222
223 if (!has_proto && !has_ports)
224 {
225 return written;
226 }
227
228 written += fprintf(stream, "[");
229
230 /* build protocol string */
231 if (has_proto)
232 {
233 struct protoent *proto = getprotobynumber(this->protocol);
234
235 if (proto)
236 {
237 written += fprintf(stream, "%s", proto->p_name);
238 serv_proto = proto->p_name;
239 }
240 else
241 {
242 written += fprintf(stream, "%d", this->protocol);
243 }
244 }
245
246 if (has_proto && has_ports)
247 {
248 written += fprintf(stream, "/");
249 }
250
251 /* build port string */
252 if (has_ports)
253 {
254 if (this->from_port == this->to_port)
255 {
256 struct servent *serv = getservbyport(htons(this->from_port), serv_proto);
257
258 if (serv)
259 {
260 written += fprintf(stream, "%s", serv->s_name);
261 }
262 else
263 {
264 written += fprintf(stream, "%d", this->from_port);
265 }
266 }
267 else
268 {
269 written += fprintf(stream, "%d-%d", this->from_port, this->to_port);
270 }
271 }
272
273 written += fprintf(stream, "]");
274
275 return written;
276 }
277
278 /**
279 * register printf() handlers
280 */
281 static void __attribute__ ((constructor))print_register()
282 {
283 register_printf_function(PRINTF_TRAFFIC_SELECTOR, print, arginfo_ptr);
284 }
285
286 /**
287 * implements traffic_selector_t.get_subset
288 */
289 static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_traffic_selector_t *other)
290 {
291 if (this->type == other->type && (this->protocol == other->protocol ||
292 this->protocol == 0 || other->protocol == 0))
293 {
294 u_int16_t from_port, to_port;
295 u_char *from, *to;
296 u_int8_t protocol;
297 size_t size;
298 private_traffic_selector_t *new_ts;
299
300 /* calculate the maximum port range allowed for both */
301 from_port = max(this->from_port, other->from_port);
302 to_port = min(this->to_port, other->to_port);
303 if (from_port > to_port)
304 {
305 return NULL;
306 }
307 /* select protocol, which is not zero */
308 protocol = max(this->protocol, other->protocol);
309
310 switch (this->type)
311 {
312 case TS_IPV4_ADDR_RANGE:
313 size = sizeof(this->from4);
314 break;
315 case TS_IPV6_ADDR_RANGE:
316 size = sizeof(this->from6);
317 break;
318 default:
319 return NULL;
320 }
321
322 /* get higher from-address */
323 if (memcmp(this->from, other->from, size) > 0)
324 {
325 from = this->from;
326 }
327 else
328 {
329 from = other->from;
330 }
331 /* get lower to-address */
332 if (memcmp(this->to, other->to, size) > 0)
333 {
334 to = other->to;
335 }
336 else
337 {
338 to = this->to;
339 }
340 /* if "from" > "to", we don't have a match */
341 if (memcmp(from, to, size) > 0)
342 {
343 return NULL;
344 }
345
346 /* we have a match in protocol, port, and address: return it... */
347 new_ts = traffic_selector_create(protocol, this->type, from_port, to_port);
348 new_ts->type = this->type;
349 new_ts->dynamic = this->dynamic || other->dynamic;
350 memcpy(new_ts->from, from, size);
351 memcpy(new_ts->to, to, size);
352
353 return &new_ts->public;
354 }
355 return NULL;
356 }
357
358 /**
359 * implements traffic_selector_t.equals
360 */
361 static bool equals(private_traffic_selector_t *this, private_traffic_selector_t *other)
362 {
363 if (this->type != other->type)
364 {
365 return FALSE;
366 }
367 if (!(this->from_port == other->from_port &&
368 this->to_port == other->to_port &&
369 this->protocol == other->protocol))
370 {
371 return FALSE;
372 }
373 switch (this->type)
374 {
375 case TS_IPV4_ADDR_RANGE:
376 if (memeq(this->from4, other->from4, sizeof(this->from4)))
377 {
378 return TRUE;
379 }
380 break;
381 case TS_IPV6_ADDR_RANGE:
382 if (memeq(this->from6, other->from6, sizeof(this->from6)))
383 {
384 return TRUE;
385 }
386 break;
387 default:
388 break;
389 }
390 return FALSE;
391 }
392
393 /**
394 * Implements traffic_selector_t.get_from_address.
395 */
396 static chunk_t get_from_address(private_traffic_selector_t *this)
397 {
398 chunk_t from = chunk_empty;
399
400 switch (this->type)
401 {
402 case TS_IPV4_ADDR_RANGE:
403 {
404 from.len = sizeof(this->from4);
405 from.ptr = malloc(from.len);
406 memcpy(from.ptr, this->from4, from.len);
407 break;
408 }
409 case TS_IPV6_ADDR_RANGE:
410 {
411 from.len = sizeof(this->from6);
412 from.ptr = malloc(from.len);
413 memcpy(from.ptr, this->from6, from.len);
414 break;
415 }
416 }
417 return from;
418 }
419
420 /**
421 * Implements traffic_selector_t.get_to_address.
422 */
423 static chunk_t get_to_address(private_traffic_selector_t *this)
424 {
425 chunk_t to = chunk_empty;
426
427 switch (this->type)
428 {
429 case TS_IPV4_ADDR_RANGE:
430 {
431 to.len = sizeof(this->to4);
432 to.ptr = malloc(to.len);
433 memcpy(to.ptr, this->to4, to.len);
434 break;
435 }
436 case TS_IPV6_ADDR_RANGE:
437 {
438 to.len = sizeof(this->to6);
439 to.ptr = malloc(to.len);
440 memcpy(to.ptr, this->to6, to.len);
441 break;
442 }
443 }
444 return to;
445 }
446
447 /**
448 * Implements traffic_selector_t.get_from_port.
449 */
450 static u_int16_t get_from_port(private_traffic_selector_t *this)
451 {
452 return this->from_port;
453 }
454
455 /**
456 * Implements traffic_selector_t.get_to_port.
457 */
458 static u_int16_t get_to_port(private_traffic_selector_t *this)
459 {
460 return this->to_port;
461 }
462
463 /**
464 * Implements traffic_selector_t.get_type.
465 */
466 static ts_type_t get_type(private_traffic_selector_t *this)
467 {
468 return this->type;
469 }
470
471 /**
472 * Implements traffic_selector_t.get_protocol.
473 */
474 static u_int8_t get_protocol(private_traffic_selector_t *this)
475 {
476 return this->protocol;
477 }
478
479 /**
480 * Implements traffic_selector_t.is_host.
481 */
482 static bool is_host(private_traffic_selector_t *this, host_t *host)
483 {
484 if (host)
485 {
486 chunk_t addr;
487 int family = host->get_family(host);
488
489 if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
490 (family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
491 {
492 addr = host->get_address(host);
493 if (memeq(addr.ptr, this->from, addr.len) &&
494 memeq(addr.ptr, this->to, addr.len))
495 {
496 return TRUE;
497 }
498 }
499 }
500 else
501 {
502 size_t length = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
503
504 if (this->dynamic)
505 {
506 return TRUE;
507 }
508
509 if (memeq(this->from, this->to, length))
510 {
511 return TRUE;
512 }
513 }
514 return FALSE;
515 }
516
517 /**
518 * Implements traffic_selector_t.set_address.
519 */
520 static void set_address(private_traffic_selector_t *this, host_t *host)
521 {
522 if (this->dynamic)
523 {
524 this->type = host->get_family(host) == AF_INET ?
525 TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE;
526
527 chunk_t from = host->get_address(host);
528 memcpy(this->from, from.ptr, from.len);
529 memcpy(this->to, from.ptr, from.len);
530 }
531 }
532
533 /**
534 * Implements traffic_selector_t.is_contained_in.
535 */
536 static bool is_contained_in(private_traffic_selector_t *this,
537 private_traffic_selector_t *other)
538 {
539 private_traffic_selector_t *subset;
540 bool contained_in = FALSE;
541
542 subset = (private_traffic_selector_t*)get_subset(this, other);
543
544 if (subset)
545 {
546 if (equals(subset, this))
547 {
548 contained_in = TRUE;
549 }
550 free(subset);
551 }
552 return contained_in;
553 }
554
555 /**
556 * Implements traffic_selector_t.includes.
557 */
558 static bool includes(private_traffic_selector_t *this, host_t *host)
559 {
560 chunk_t addr;
561 int family = host->get_family(host);
562
563 if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
564 (family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
565 {
566 addr = host->get_address(host);
567
568 return memcmp(this->from, addr.ptr, addr.len) <= 0 &&
569 memcmp(this->to, addr.ptr, addr.len) >= 0;
570 }
571
572 return FALSE;
573 }
574
575 /**
576 * Implements traffic_selector_t.clone.
577 */
578 static traffic_selector_t *clone_(private_traffic_selector_t *this)
579 {
580 private_traffic_selector_t *clone;
581
582 clone = traffic_selector_create(this->protocol, this->type,
583 this->from_port, this->to_port);
584
585 clone->dynamic = this->dynamic;
586 switch (clone->type)
587 {
588 case TS_IPV4_ADDR_RANGE:
589 {
590 memcpy(clone->from4, this->from4, sizeof(this->from4));
591 memcpy(clone->to4, this->to4, sizeof(this->to4));
592 return &clone->public;
593 }
594 case TS_IPV6_ADDR_RANGE:
595 {
596 memcpy(clone->from6, this->from6, sizeof(this->from6));
597 memcpy(clone->to6, this->to6, sizeof(this->to6));
598 return &clone->public;
599 }
600 default:
601 {
602 /* unreachable */
603 return &clone->public;
604 }
605 }
606 }
607
608 /**
609 * Implements traffic_selector_t.destroy.
610 */
611 static void destroy(private_traffic_selector_t *this)
612 {
613 free(this);
614 }
615
616 /*
617 * see header
618 */
619 traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol,
620 ts_type_t type,
621 chunk_t from, u_int16_t from_port,
622 chunk_t to, u_int16_t to_port)
623 {
624 private_traffic_selector_t *this = traffic_selector_create(protocol, type,
625 from_port, to_port);
626
627 switch (type)
628 {
629 case TS_IPV4_ADDR_RANGE:
630 {
631 if (from.len != 4 || to.len != 4)
632 {
633 free(this);
634 return NULL;
635 }
636 memcpy(this->from4, from.ptr, from.len);
637 memcpy(this->to4, to.ptr, to.len);
638 break;
639 }
640 case TS_IPV6_ADDR_RANGE:
641 {
642 if (from.len != 16 || to.len != 16)
643 {
644 free(this);
645 return NULL;
646 }
647 memcpy(this->from6, from.ptr, from.len);
648 memcpy(this->to6, to.ptr, to.len);
649 break;
650 }
651 default:
652 {
653 free(this);
654 return NULL;
655 }
656 }
657 return (&this->public);
658 }
659
660 /*
661 * see header
662 */
663 traffic_selector_t *traffic_selector_create_from_subnet(host_t *net,
664 u_int8_t netbits, u_int8_t protocol, u_int16_t port)
665 {
666 private_traffic_selector_t *this = traffic_selector_create(protocol, 0, 0, 65535);
667
668 switch (net->get_family(net))
669 {
670 case AF_INET:
671 {
672 chunk_t from;
673
674 this->type = TS_IPV4_ADDR_RANGE;
675 from = net->get_address(net);
676 memcpy(this->from4, from.ptr, from.len);
677 if (this->from4[0] == 0)
678 {
679 /* use /0 for 0.0.0.0 */
680 this->to4[0] = ~0;
681 }
682 else
683 {
684 calc_range(this, netbits);
685 }
686 break;
687 }
688 case AF_INET6:
689 {
690 chunk_t from;
691
692 this->type = TS_IPV6_ADDR_RANGE;
693 from = net->get_address(net);
694 memcpy(this->from6, from.ptr, from.len);
695 if (this->from6[0] == 0 && this->from6[1] == 0 &&
696 this->from6[2] == 0 && this->from6[3] == 0)
697 {
698 /* use /0 for ::0 */
699 this->to6[0] = ~0;
700 this->to6[1] = ~0;
701 this->to6[2] = ~0;
702 this->to6[3] = ~0;
703 }
704 else
705 {
706 calc_range(this, netbits);
707 }
708 break;
709 }
710 default:
711 {
712 free(this);
713 return NULL;
714 }
715 }
716 if (port)
717 {
718 this->from_port = port;
719 this->to_port = port;
720 }
721 return (&this->public);
722 }
723
724 /*
725 * see header
726 */
727 traffic_selector_t *traffic_selector_create_from_string(
728 u_int8_t protocol, ts_type_t type,
729 char *from_addr, u_int16_t from_port,
730 char *to_addr, u_int16_t to_port)
731 {
732 private_traffic_selector_t *this = traffic_selector_create(protocol, type,
733 from_port, to_port);
734
735 this->type = type;
736 switch (type)
737 {
738 case TS_IPV4_ADDR_RANGE:
739 {
740 if (inet_pton(AF_INET, from_addr, (struct in_addr*)this->from4) < 0)
741 {
742 free(this);
743 return NULL;
744 }
745 if (inet_pton(AF_INET, to_addr, (struct in_addr*)this->to4) < 0)
746 {
747 free(this);
748 return NULL;
749 }
750 break;
751 }
752 case TS_IPV6_ADDR_RANGE:
753 {
754 if (inet_pton(AF_INET6, from_addr, (struct in6_addr*)this->from6) < 0)
755 {
756 free(this);
757 return NULL;
758 }
759 if (inet_pton(AF_INET6, to_addr, (struct in6_addr*)this->to6) < 0)
760 {
761 free(this);
762 return NULL;
763 }
764 break;
765 }
766 }
767 return (&this->public);
768 }
769
770 /*
771 * see header
772 */
773 traffic_selector_t *traffic_selector_create_dynamic(
774 u_int8_t protocol, ts_type_t type,
775 u_int16_t from_port, u_int16_t to_port)
776 {
777 private_traffic_selector_t *this = traffic_selector_create(protocol, type,
778 from_port, to_port);
779
780 memset(this->from6, 0, sizeof(this->from6));
781 memset(this->to6, 0xFF, sizeof(this->to6));
782
783 this->dynamic = TRUE;
784
785 return &this->public;
786 }
787
788 /*
789 * see declaration
790 */
791 static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol,
792 ts_type_t type, u_int16_t from_port, u_int16_t to_port)
793 {
794 private_traffic_selector_t *this = malloc_thing(private_traffic_selector_t);
795
796 /* public functions */
797 this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset;
798 this->public.equals = (bool(*)(traffic_selector_t*,traffic_selector_t*))equals;
799 this->public.get_from_address = (chunk_t(*)(traffic_selector_t*))get_from_address;
800 this->public.get_to_address = (chunk_t(*)(traffic_selector_t*))get_to_address;
801 this->public.get_from_port = (u_int16_t(*)(traffic_selector_t*))get_from_port;
802 this->public.get_to_port = (u_int16_t(*)(traffic_selector_t*))get_to_port;
803 this->public.get_type = (ts_type_t(*)(traffic_selector_t*))get_type;
804 this->public.get_protocol = (u_int8_t(*)(traffic_selector_t*))get_protocol;
805 this->public.is_host = (bool(*)(traffic_selector_t*,host_t*))is_host;
806 this->public.is_contained_in = (bool(*)(traffic_selector_t*,traffic_selector_t*))is_contained_in;
807 this->public.includes = (bool(*)(traffic_selector_t*,host_t*))includes;
808 this->public.set_address = (void(*)(traffic_selector_t*,host_t*))set_address;
809 this->public.clone = (traffic_selector_t*(*)(traffic_selector_t*))clone_;
810 this->public.destroy = (void(*)(traffic_selector_t*))destroy;
811
812 this->from_port = from_port;
813 this->to_port = to_port;
814 this->protocol = protocol;
815 this->type = type;
816 this->dynamic = FALSE;
817
818 return this;
819 }
820
821 /* vim: set ts=4 sw=4 noet: */