Support "opaque" ports in traffic selector subset calculation
[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
316 {
317 written += print_in_hook(data, "%d-%d",
318 this->from_port, this->to_port);
319 }
320 }
321
322 written += print_in_hook(data, "]");
323
324 return written;
325 }
326
327 METHOD(traffic_selector_t, get_subset, traffic_selector_t*,
328 private_traffic_selector_t *this, traffic_selector_t *other_public)
329 {
330 private_traffic_selector_t *other, *subset;
331 u_int16_t from_port, to_port;
332 u_char *from, *to;
333 u_int8_t protocol;
334 size_t size;
335
336 other = (private_traffic_selector_t*)other_public;
337
338 if (this->dynamic || other->dynamic)
339 { /* no set_address() applied, TS has no subset */
340 return NULL;
341 }
342
343 if (this->type != other->type)
344 {
345 return NULL;
346 }
347 switch (this->type)
348 {
349 case TS_IPV4_ADDR_RANGE:
350 size = sizeof(this->from4);
351 break;
352 case TS_IPV6_ADDR_RANGE:
353 size = sizeof(this->from6);
354 break;
355 default:
356 return NULL;
357 }
358
359 if (this->protocol != other->protocol &&
360 this->protocol != 0 && other->protocol != 0)
361 {
362 return NULL;
363 }
364 /* select protocol, which is not zero */
365 protocol = max(this->protocol, other->protocol);
366
367 if ((is_opaque(this) && is_opaque(other)) ||
368 (is_opaque(this) && is_any(other)) ||
369 (is_opaque(other) && is_any(this)))
370 {
371 from_port = 0xffff;
372 to_port = 0;
373 }
374 else
375 {
376 /* calculate the maximum port range allowed for both */
377 from_port = max(this->from_port, other->from_port);
378 to_port = min(this->to_port, other->to_port);
379 if (from_port > to_port)
380 {
381 return NULL;
382 }
383 }
384 /* get higher from-address */
385 if (memcmp(this->from, other->from, size) > 0)
386 {
387 from = this->from;
388 }
389 else
390 {
391 from = other->from;
392 }
393 /* get lower to-address */
394 if (memcmp(this->to, other->to, size) > 0)
395 {
396 to = other->to;
397 }
398 else
399 {
400 to = this->to;
401 }
402 /* if "from" > "to", we don't have a match */
403 if (memcmp(from, to, size) > 0)
404 {
405 return NULL;
406 }
407
408 /* we have a match in protocol, port, and address: return it... */
409 subset = traffic_selector_create(protocol, this->type, from_port, to_port);
410 memcpy(subset->from, from, size);
411 memcpy(subset->to, to, size);
412 calc_netbits(subset);
413
414 return &subset->public;
415 }
416
417 METHOD(traffic_selector_t, equals, bool,
418 private_traffic_selector_t *this, traffic_selector_t *other_public)
419 {
420 private_traffic_selector_t *other;
421
422 other = (private_traffic_selector_t*)other_public;
423 if (this->type != other->type)
424 {
425 return FALSE;
426 }
427 if (!(this->from_port == other->from_port &&
428 this->to_port == other->to_port &&
429 this->protocol == other->protocol))
430 {
431 return FALSE;
432 }
433 switch (this->type)
434 {
435 case TS_IPV4_ADDR_RANGE:
436 if (memeq(this->from4, other->from4, sizeof(this->from4)) &&
437 memeq(this->to4, other->to4, sizeof(this->to4)))
438 {
439 return TRUE;
440 }
441 break;
442 case TS_IPV6_ADDR_RANGE:
443 if (memeq(this->from6, other->from6, sizeof(this->from6)) &&
444 memeq(this->to6, other->to6, sizeof(this->to6)))
445 {
446 return TRUE;
447 }
448 break;
449 default:
450 break;
451 }
452 return FALSE;
453 }
454
455 METHOD(traffic_selector_t, get_from_address, chunk_t,
456 private_traffic_selector_t *this)
457 {
458 switch (this->type)
459 {
460 case TS_IPV4_ADDR_RANGE:
461 return chunk_create(this->from, sizeof(this->from4));
462 case TS_IPV6_ADDR_RANGE:
463 return chunk_create(this->from, sizeof(this->from6));
464 default:
465 return chunk_empty;
466 }
467 }
468
469 METHOD(traffic_selector_t, get_to_address, chunk_t,
470 private_traffic_selector_t *this)
471 {
472 switch (this->type)
473 {
474 case TS_IPV4_ADDR_RANGE:
475 return chunk_create(this->to, sizeof(this->to4));
476 case TS_IPV6_ADDR_RANGE:
477 return chunk_create(this->to, sizeof(this->to6));
478 default:
479 return chunk_empty;
480 }
481 }
482
483 METHOD(traffic_selector_t, get_from_port, u_int16_t,
484 private_traffic_selector_t *this)
485 {
486 return this->from_port;
487 }
488
489 METHOD(traffic_selector_t, get_to_port, u_int16_t,
490 private_traffic_selector_t *this)
491 {
492 return this->to_port;
493 }
494
495 METHOD(traffic_selector_t, get_type, ts_type_t,
496 private_traffic_selector_t *this)
497 {
498 return this->type;
499 }
500
501 METHOD(traffic_selector_t, get_protocol, u_int8_t,
502 private_traffic_selector_t *this)
503 {
504 return this->protocol;
505 }
506
507 METHOD(traffic_selector_t, is_host, bool,
508 private_traffic_selector_t *this, host_t *host)
509 {
510 if (host)
511 {
512 chunk_t addr;
513 int family = host->get_family(host);
514
515 if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
516 (family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
517 {
518 addr = host->get_address(host);
519 if (memeq(addr.ptr, this->from, addr.len) &&
520 memeq(addr.ptr, this->to, addr.len))
521 {
522 return TRUE;
523 }
524 }
525 }
526 else
527 {
528 size_t length = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
529
530 if (this->dynamic)
531 {
532 return TRUE;
533 }
534
535 if (memeq(this->from, this->to, length))
536 {
537 return TRUE;
538 }
539 }
540 return FALSE;
541 }
542
543 METHOD(traffic_selector_t, is_dynamic, bool,
544 private_traffic_selector_t *this)
545 {
546 return this->dynamic;
547 }
548
549 METHOD(traffic_selector_t, set_address, void,
550 private_traffic_selector_t *this, host_t *host)
551 {
552 if (is_host(this, NULL))
553 {
554 this->type = host->get_family(host) == AF_INET ?
555 TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE;
556
557 if (host->is_anyaddr(host))
558 {
559 memset(this->from6, 0x00, sizeof(this->from6));
560 memset(this->to6, 0xFF, sizeof(this->to6));
561 this->netbits = 0;
562 }
563 else
564 {
565 chunk_t from = host->get_address(host);
566 memcpy(this->from, from.ptr, from.len);
567 memcpy(this->to, from.ptr, from.len);
568 this->netbits = from.len * 8;
569 }
570 this->dynamic = FALSE;
571 }
572 }
573
574 METHOD(traffic_selector_t, is_contained_in, bool,
575 private_traffic_selector_t *this, traffic_selector_t *other)
576 {
577 private_traffic_selector_t *subset;
578 bool contained_in = FALSE;
579
580 subset = (private_traffic_selector_t*)get_subset(this, other);
581
582 if (subset)
583 {
584 if (equals(subset, &this->public))
585 {
586 contained_in = TRUE;
587 }
588 free(subset);
589 }
590 return contained_in;
591 }
592
593 METHOD(traffic_selector_t, includes, bool,
594 private_traffic_selector_t *this, host_t *host)
595 {
596 chunk_t addr;
597 int family = host->get_family(host);
598
599 if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
600 (family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
601 {
602 addr = host->get_address(host);
603
604 return memcmp(this->from, addr.ptr, addr.len) <= 0 &&
605 memcmp(this->to, addr.ptr, addr.len) >= 0;
606 }
607
608 return FALSE;
609 }
610
611 METHOD(traffic_selector_t, to_subnet, bool,
612 private_traffic_selector_t *this, host_t **net, u_int8_t *mask)
613 {
614 /* there is no way to do this cleanly, as the address range may
615 * be anything else but a subnet. We use from_addr as subnet
616 * and try to calculate a usable subnet mask.
617 */
618 int family, non_zero_bytes;
619 u_int16_t port = 0;
620 chunk_t net_chunk;
621
622 *mask = (this->netbits == NON_SUBNET_ADDRESS_RANGE) ? calc_netbits(this)
623 : this->netbits;
624
625 switch (this->type)
626 {
627 case TS_IPV4_ADDR_RANGE:
628 family = AF_INET;
629 net_chunk.len = sizeof(this->from4);
630 break;
631 case TS_IPV6_ADDR_RANGE:
632 family = AF_INET6;
633 net_chunk.len = sizeof(this->from6);
634 break;
635 default:
636 /* unreachable */
637 return FALSE;
638 }
639
640 net_chunk.ptr = malloc(net_chunk.len);
641 memset(net_chunk.ptr, 0x00, net_chunk.len);
642 if (*mask)
643 {
644 non_zero_bytes = (*mask + 7) / 8;
645 memcpy(net_chunk.ptr, this->from, non_zero_bytes);
646 net_chunk.ptr[non_zero_bytes-1] &= 0xFF << (8 * non_zero_bytes - *mask);
647 }
648
649 if (this->to_port == this->from_port)
650 {
651 port = this->to_port;
652 }
653
654 *net = host_create_from_chunk(family, net_chunk, port);
655 chunk_free(&net_chunk);
656
657 return this->netbits != NON_SUBNET_ADDRESS_RANGE;
658 }
659
660 METHOD(traffic_selector_t, clone_, traffic_selector_t*,
661 private_traffic_selector_t *this)
662 {
663 private_traffic_selector_t *clone;
664
665 clone = traffic_selector_create(this->protocol, this->type,
666 this->from_port, this->to_port);
667 clone->netbits = this->netbits;
668 clone->dynamic = this->dynamic;
669
670 switch (clone->type)
671 {
672 case TS_IPV4_ADDR_RANGE:
673 memcpy(clone->from4, this->from4, sizeof(this->from4));
674 memcpy(clone->to4, this->to4, sizeof(this->to4));
675 return &clone->public;
676 case TS_IPV6_ADDR_RANGE:
677 memcpy(clone->from6, this->from6, sizeof(this->from6));
678 memcpy(clone->to6, this->to6, sizeof(this->to6));
679 return &clone->public;
680 default:
681 /* unreachable */
682 return &clone->public;
683 }
684 }
685
686 METHOD(traffic_selector_t, destroy, void,
687 private_traffic_selector_t *this)
688 {
689 free(this);
690 }
691
692 /*
693 * see header
694 */
695 traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol,
696 ts_type_t type,
697 chunk_t from, u_int16_t from_port,
698 chunk_t to, u_int16_t to_port)
699 {
700 private_traffic_selector_t *this = traffic_selector_create(protocol, type,
701 from_port, to_port);
702
703 switch (type)
704 {
705 case TS_IPV4_ADDR_RANGE:
706 if (from.len != 4 || to.len != 4)
707 {
708 free(this);
709 return NULL;
710 }
711 memcpy(this->from4, from.ptr, from.len);
712 memcpy(this->to4, to.ptr, to.len);
713 break;
714 case TS_IPV6_ADDR_RANGE:
715 if (from.len != 16 || to.len != 16)
716 {
717 free(this);
718 return NULL;
719 }
720 memcpy(this->from6, from.ptr, from.len);
721 memcpy(this->to6, to.ptr, to.len);
722 break;
723 default:
724 free(this);
725 return NULL;
726 }
727 calc_netbits(this);
728 return (&this->public);
729 }
730
731 /*
732 * see header
733 */
734 traffic_selector_t *traffic_selector_create_from_rfc3779_format(ts_type_t type,
735 chunk_t from, chunk_t to)
736 {
737 size_t len;
738 private_traffic_selector_t *this = traffic_selector_create(0, type, 0, 65535);
739
740 switch (type)
741 {
742 case TS_IPV4_ADDR_RANGE:
743 len = 4;
744 break;
745 case TS_IPV6_ADDR_RANGE:
746 len = 16;
747 break;
748 default:
749 free(this);
750 return NULL;
751 }
752 memset(this->from, 0x00, len);
753 memset(this->to , 0xff, len);
754
755 if (from.len > 1)
756 {
757 memcpy(this->from, from.ptr+1, from.len-1);
758 }
759 if (to.len > 1)
760 {
761 u_int8_t mask = to.ptr[0] ? (1 << to.ptr[0]) - 1 : 0;
762
763 memcpy(this->to, to.ptr+1, to.len-1);
764 this->to[to.len-2] |= mask;
765 }
766 this->netbits = chunk_equals(from, to) ? (from.len-1)*8 - from.ptr[0]
767 : NON_SUBNET_ADDRESS_RANGE;
768 return (&this->public);
769 }
770
771 /*
772 * see header
773 */
774 traffic_selector_t *traffic_selector_create_from_subnet(host_t *net,
775 u_int8_t netbits, u_int8_t protocol, u_int16_t port)
776 {
777 private_traffic_selector_t *this;
778 chunk_t from;
779
780 this = traffic_selector_create(protocol, 0, 0, 65535);
781
782 switch (net->get_family(net))
783 {
784 case AF_INET:
785 this->type = TS_IPV4_ADDR_RANGE;
786 break;
787 case AF_INET6:
788 this->type = TS_IPV6_ADDR_RANGE;
789 break;
790 default:
791 net->destroy(net);
792 free(this);
793 return NULL;
794 }
795 from = net->get_address(net);
796 memcpy(this->from, from.ptr, from.len);
797 netbits = min(netbits, this->type == TS_IPV4_ADDR_RANGE ? 32 : 128);
798 calc_range(this, netbits);
799 if (port)
800 {
801 this->from_port = port;
802 this->to_port = port;
803 }
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(char *string,
855 u_int8_t protocol, u_int16_t port)
856 {
857 host_t *net;
858 int bits;
859
860 net = host_create_from_subnet(string, &bits);
861 if (net)
862 {
863 return traffic_selector_create_from_subnet(net, bits, protocol, port);
864 }
865 return NULL;
866 }
867
868 /*
869 * see header
870 */
871 traffic_selector_t *traffic_selector_create_dynamic(u_int8_t protocol,
872 u_int16_t from_port, u_int16_t to_port)
873 {
874 private_traffic_selector_t *this = traffic_selector_create(
875 protocol, TS_IPV4_ADDR_RANGE, from_port, to_port);
876
877 memset(this->from6, 0, sizeof(this->from6));
878 memset(this->to6, 0xFF, sizeof(this->to6));
879 this->netbits = 0;
880 this->dynamic = TRUE;
881
882 return &this->public;
883 }
884
885 /*
886 * see declaration
887 */
888 static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol,
889 ts_type_t type, u_int16_t from_port, u_int16_t to_port)
890 {
891 private_traffic_selector_t *this;
892
893 INIT(this,
894 .public = {
895 .get_subset = _get_subset,
896 .equals = _equals,
897 .get_from_address = _get_from_address,
898 .get_to_address = _get_to_address,
899 .get_from_port = _get_from_port,
900 .get_to_port = _get_to_port,
901 .get_type = _get_type,
902 .get_protocol = _get_protocol,
903 .is_host = _is_host,
904 .is_dynamic = _is_dynamic,
905 .is_contained_in = _is_contained_in,
906 .includes = _includes,
907 .set_address = _set_address,
908 .to_subnet = _to_subnet,
909 .clone = _clone_,
910 .destroy = _destroy,
911 },
912 .from_port = from_port,
913 .to_port = to_port,
914 .protocol = protocol,
915 .type = type,
916 );
917
918 return this;
919 }