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