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