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