Slightly refactor traffic_selector_t.get_subset()
[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 * Described in header.
182 */
183 int traffic_selector_printf_hook(printf_hook_data_t *data,
184 printf_hook_spec_t *spec, const void *const *args)
185 {
186 private_traffic_selector_t *this = *((private_traffic_selector_t**)(args[0]));
187 linked_list_t *list = *((linked_list_t**)(args[0]));
188 enumerator_t *enumerator;
189 char from_str[INET6_ADDRSTRLEN] = "";
190 char to_str[INET6_ADDRSTRLEN] = "";
191 char *serv_proto = NULL;
192 bool has_proto;
193 bool has_ports;
194 size_t written = 0;
195 u_int32_t from[4], to[4];
196
197 if (this == NULL)
198 {
199 return print_in_hook(data, "(null)");
200 }
201
202 if (spec->hash)
203 {
204 enumerator = list->create_enumerator(list);
205 while (enumerator->enumerate(enumerator, (void**)&this))
206 {
207 /* call recursivly */
208 written += print_in_hook(data, "%R ", this);
209 }
210 enumerator->destroy(enumerator);
211 return written;
212 }
213
214 memset(from, 0, sizeof(from));
215 memset(to, 0xFF, sizeof(to));
216 if (this->dynamic &&
217 memeq(this->from, from, this->type == TS_IPV4_ADDR_RANGE ? 4 : 16) &&
218 memeq(this->to, to, this->type == TS_IPV4_ADDR_RANGE ? 4 : 16))
219 {
220 written += print_in_hook(data, "dynamic");
221 }
222 else
223 {
224 if (this->type == TS_IPV4_ADDR_RANGE)
225 {
226 inet_ntop(AF_INET, &this->from4, from_str, sizeof(from_str));
227 }
228 else
229 {
230 inet_ntop(AF_INET6, &this->from6, from_str, sizeof(from_str));
231 }
232 if (this->netbits == NON_SUBNET_ADDRESS_RANGE)
233 {
234 if (this->type == TS_IPV4_ADDR_RANGE)
235 {
236 inet_ntop(AF_INET, &this->to4, to_str, sizeof(to_str));
237 }
238 else
239 {
240 inet_ntop(AF_INET6, &this->to6, to_str, sizeof(to_str));
241 }
242 written += print_in_hook(data, "%s..%s", from_str, to_str);
243 }
244 else
245 {
246 written += print_in_hook(data, "%s/%d", from_str, this->netbits);
247 }
248 }
249
250 /* check if we have protocol and/or port selectors */
251 has_proto = this->protocol != 0;
252 has_ports = !(this->from_port == 0 && this->to_port == 0xFFFF);
253
254 if (!has_proto && !has_ports)
255 {
256 return written;
257 }
258
259 written += print_in_hook(data, "[");
260
261 /* build protocol string */
262 if (has_proto)
263 {
264 struct protoent *proto = getprotobynumber(this->protocol);
265
266 if (proto)
267 {
268 written += print_in_hook(data, "%s", proto->p_name);
269 serv_proto = proto->p_name;
270 }
271 else
272 {
273 written += print_in_hook(data, "%d", this->protocol);
274 }
275 }
276
277 if (has_proto && has_ports)
278 {
279 written += print_in_hook(data, "/");
280 }
281
282 /* build port string */
283 if (has_ports)
284 {
285 if (this->from_port == this->to_port)
286 {
287 struct servent *serv;
288
289 serv = getservbyport(htons(this->from_port), serv_proto);
290 if (serv)
291 {
292 written += print_in_hook(data, "%s", serv->s_name);
293 }
294 else
295 {
296 written += print_in_hook(data, "%d", this->from_port);
297 }
298 }
299 else
300 {
301 written += print_in_hook(data, "%d-%d",
302 this->from_port, this->to_port);
303 }
304 }
305
306 written += print_in_hook(data, "]");
307
308 return written;
309 }
310
311 METHOD(traffic_selector_t, get_subset, traffic_selector_t*,
312 private_traffic_selector_t *this, traffic_selector_t *other_public)
313 {
314 private_traffic_selector_t *other, *subset;
315 u_int16_t from_port, to_port;
316 u_char *from, *to;
317 u_int8_t protocol;
318 size_t size;
319
320 other = (private_traffic_selector_t*)other_public;
321
322 if (this->dynamic || other->dynamic)
323 { /* no set_address() applied, TS has no subset */
324 return NULL;
325 }
326
327 if (this->type != other->type)
328 {
329 return NULL;
330 }
331 switch (this->type)
332 {
333 case TS_IPV4_ADDR_RANGE:
334 size = sizeof(this->from4);
335 break;
336 case TS_IPV6_ADDR_RANGE:
337 size = sizeof(this->from6);
338 break;
339 default:
340 return NULL;
341 }
342
343 if (this->protocol != other->protocol &&
344 this->protocol != 0 && other->protocol != 0)
345 {
346 return NULL;
347 }
348 /* select protocol, which is not zero */
349 protocol = max(this->protocol, other->protocol);
350
351 /* calculate the maximum port range allowed for both */
352 from_port = max(this->from_port, other->from_port);
353 to_port = min(this->to_port, other->to_port);
354 if (from_port > to_port)
355 {
356 return NULL;
357 }
358 /* get higher from-address */
359 if (memcmp(this->from, other->from, size) > 0)
360 {
361 from = this->from;
362 }
363 else
364 {
365 from = other->from;
366 }
367 /* get lower to-address */
368 if (memcmp(this->to, other->to, size) > 0)
369 {
370 to = other->to;
371 }
372 else
373 {
374 to = this->to;
375 }
376 /* if "from" > "to", we don't have a match */
377 if (memcmp(from, to, size) > 0)
378 {
379 return NULL;
380 }
381
382 /* we have a match in protocol, port, and address: return it... */
383 subset = traffic_selector_create(protocol, this->type, from_port, to_port);
384 memcpy(subset->from, from, size);
385 memcpy(subset->to, to, size);
386 calc_netbits(subset);
387
388 return &subset->public;
389 }
390
391 METHOD(traffic_selector_t, equals, bool,
392 private_traffic_selector_t *this, traffic_selector_t *other_public)
393 {
394 private_traffic_selector_t *other;
395
396 other = (private_traffic_selector_t*)other_public;
397 if (this->type != other->type)
398 {
399 return FALSE;
400 }
401 if (!(this->from_port == other->from_port &&
402 this->to_port == other->to_port &&
403 this->protocol == other->protocol))
404 {
405 return FALSE;
406 }
407 switch (this->type)
408 {
409 case TS_IPV4_ADDR_RANGE:
410 if (memeq(this->from4, other->from4, sizeof(this->from4)) &&
411 memeq(this->to4, other->to4, sizeof(this->to4)))
412 {
413 return TRUE;
414 }
415 break;
416 case TS_IPV6_ADDR_RANGE:
417 if (memeq(this->from6, other->from6, sizeof(this->from6)) &&
418 memeq(this->to6, other->to6, sizeof(this->to6)))
419 {
420 return TRUE;
421 }
422 break;
423 default:
424 break;
425 }
426 return FALSE;
427 }
428
429 METHOD(traffic_selector_t, get_from_address, chunk_t,
430 private_traffic_selector_t *this)
431 {
432 switch (this->type)
433 {
434 case TS_IPV4_ADDR_RANGE:
435 return chunk_create(this->from, sizeof(this->from4));
436 case TS_IPV6_ADDR_RANGE:
437 return chunk_create(this->from, sizeof(this->from6));
438 default:
439 return chunk_empty;
440 }
441 }
442
443 METHOD(traffic_selector_t, get_to_address, chunk_t,
444 private_traffic_selector_t *this)
445 {
446 switch (this->type)
447 {
448 case TS_IPV4_ADDR_RANGE:
449 return chunk_create(this->to, sizeof(this->to4));
450 case TS_IPV6_ADDR_RANGE:
451 return chunk_create(this->to, sizeof(this->to6));
452 default:
453 return chunk_empty;
454 }
455 }
456
457 METHOD(traffic_selector_t, get_from_port, u_int16_t,
458 private_traffic_selector_t *this)
459 {
460 return this->from_port;
461 }
462
463 METHOD(traffic_selector_t, get_to_port, u_int16_t,
464 private_traffic_selector_t *this)
465 {
466 return this->to_port;
467 }
468
469 METHOD(traffic_selector_t, get_type, ts_type_t,
470 private_traffic_selector_t *this)
471 {
472 return this->type;
473 }
474
475 METHOD(traffic_selector_t, get_protocol, u_int8_t,
476 private_traffic_selector_t *this)
477 {
478 return this->protocol;
479 }
480
481 METHOD(traffic_selector_t, is_host, bool,
482 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 METHOD(traffic_selector_t, is_dynamic, bool,
518 private_traffic_selector_t *this)
519 {
520 return this->dynamic;
521 }
522
523 METHOD(traffic_selector_t, set_address, void,
524 private_traffic_selector_t *this, host_t *host)
525 {
526 if (is_host(this, NULL))
527 {
528 this->type = host->get_family(host) == AF_INET ?
529 TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE;
530
531 if (host->is_anyaddr(host))
532 {
533 memset(this->from6, 0x00, sizeof(this->from6));
534 memset(this->to6, 0xFF, sizeof(this->to6));
535 this->netbits = 0;
536 }
537 else
538 {
539 chunk_t from = host->get_address(host);
540 memcpy(this->from, from.ptr, from.len);
541 memcpy(this->to, from.ptr, from.len);
542 this->netbits = from.len * 8;
543 }
544 this->dynamic = FALSE;
545 }
546 }
547
548 METHOD(traffic_selector_t, is_contained_in, bool,
549 private_traffic_selector_t *this, traffic_selector_t *other)
550 {
551 private_traffic_selector_t *subset;
552 bool contained_in = FALSE;
553
554 subset = (private_traffic_selector_t*)get_subset(this, other);
555
556 if (subset)
557 {
558 if (equals(subset, &this->public))
559 {
560 contained_in = TRUE;
561 }
562 free(subset);
563 }
564 return contained_in;
565 }
566
567 METHOD(traffic_selector_t, includes, bool,
568 private_traffic_selector_t *this, host_t *host)
569 {
570 chunk_t addr;
571 int family = host->get_family(host);
572
573 if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
574 (family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
575 {
576 addr = host->get_address(host);
577
578 return memcmp(this->from, addr.ptr, addr.len) <= 0 &&
579 memcmp(this->to, addr.ptr, addr.len) >= 0;
580 }
581
582 return FALSE;
583 }
584
585 METHOD(traffic_selector_t, to_subnet, bool,
586 private_traffic_selector_t *this, host_t **net, u_int8_t *mask)
587 {
588 /* there is no way to do this cleanly, as the address range may
589 * be anything else but a subnet. We use from_addr as subnet
590 * and try to calculate a usable subnet mask.
591 */
592 int family, non_zero_bytes;
593 u_int16_t port = 0;
594 chunk_t net_chunk;
595
596 *mask = (this->netbits == NON_SUBNET_ADDRESS_RANGE) ? calc_netbits(this)
597 : this->netbits;
598
599 switch (this->type)
600 {
601 case TS_IPV4_ADDR_RANGE:
602 family = AF_INET;
603 net_chunk.len = sizeof(this->from4);
604 break;
605 case TS_IPV6_ADDR_RANGE:
606 family = AF_INET6;
607 net_chunk.len = sizeof(this->from6);
608 break;
609 default:
610 /* unreachable */
611 return FALSE;
612 }
613
614 net_chunk.ptr = malloc(net_chunk.len);
615 memset(net_chunk.ptr, 0x00, net_chunk.len);
616 if (*mask)
617 {
618 non_zero_bytes = (*mask + 7) / 8;
619 memcpy(net_chunk.ptr, this->from, non_zero_bytes);
620 net_chunk.ptr[non_zero_bytes-1] &= 0xFF << (8 * non_zero_bytes - *mask);
621 }
622
623 if (this->to_port == this->from_port)
624 {
625 port = this->to_port;
626 }
627
628 *net = host_create_from_chunk(family, net_chunk, port);
629 chunk_free(&net_chunk);
630
631 return this->netbits != NON_SUBNET_ADDRESS_RANGE;
632 }
633
634 METHOD(traffic_selector_t, clone_, traffic_selector_t*,
635 private_traffic_selector_t *this)
636 {
637 private_traffic_selector_t *clone;
638
639 clone = traffic_selector_create(this->protocol, this->type,
640 this->from_port, this->to_port);
641 clone->netbits = this->netbits;
642 clone->dynamic = this->dynamic;
643
644 switch (clone->type)
645 {
646 case TS_IPV4_ADDR_RANGE:
647 memcpy(clone->from4, this->from4, sizeof(this->from4));
648 memcpy(clone->to4, this->to4, sizeof(this->to4));
649 return &clone->public;
650 case TS_IPV6_ADDR_RANGE:
651 memcpy(clone->from6, this->from6, sizeof(this->from6));
652 memcpy(clone->to6, this->to6, sizeof(this->to6));
653 return &clone->public;
654 default:
655 /* unreachable */
656 return &clone->public;
657 }
658 }
659
660 METHOD(traffic_selector_t, destroy, void,
661 private_traffic_selector_t *this)
662 {
663 free(this);
664 }
665
666 /*
667 * see header
668 */
669 traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol,
670 ts_type_t type,
671 chunk_t from, u_int16_t from_port,
672 chunk_t to, u_int16_t to_port)
673 {
674 private_traffic_selector_t *this = traffic_selector_create(protocol, type,
675 from_port, to_port);
676
677 switch (type)
678 {
679 case TS_IPV4_ADDR_RANGE:
680 if (from.len != 4 || to.len != 4)
681 {
682 free(this);
683 return NULL;
684 }
685 memcpy(this->from4, from.ptr, from.len);
686 memcpy(this->to4, to.ptr, to.len);
687 break;
688 case TS_IPV6_ADDR_RANGE:
689 if (from.len != 16 || to.len != 16)
690 {
691 free(this);
692 return NULL;
693 }
694 memcpy(this->from6, from.ptr, from.len);
695 memcpy(this->to6, to.ptr, to.len);
696 break;
697 default:
698 free(this);
699 return NULL;
700 }
701 calc_netbits(this);
702 return (&this->public);
703 }
704
705 /*
706 * see header
707 */
708 traffic_selector_t *traffic_selector_create_from_rfc3779_format(ts_type_t type,
709 chunk_t from, chunk_t to)
710 {
711 size_t len;
712 private_traffic_selector_t *this = traffic_selector_create(0, type, 0, 65535);
713
714 switch (type)
715 {
716 case TS_IPV4_ADDR_RANGE:
717 len = 4;
718 break;
719 case TS_IPV6_ADDR_RANGE:
720 len = 16;
721 break;
722 default:
723 free(this);
724 return NULL;
725 }
726 memset(this->from, 0x00, len);
727 memset(this->to , 0xff, len);
728
729 if (from.len > 1)
730 {
731 memcpy(this->from, from.ptr+1, from.len-1);
732 }
733 if (to.len > 1)
734 {
735 u_int8_t mask = to.ptr[0] ? (1 << to.ptr[0]) - 1 : 0;
736
737 memcpy(this->to, to.ptr+1, to.len-1);
738 this->to[to.len-2] |= mask;
739 }
740 this->netbits = chunk_equals(from, to) ? (from.len-1)*8 - from.ptr[0]
741 : NON_SUBNET_ADDRESS_RANGE;
742 return (&this->public);
743 }
744
745 /*
746 * see header
747 */
748 traffic_selector_t *traffic_selector_create_from_subnet(host_t *net,
749 u_int8_t netbits, u_int8_t protocol, u_int16_t port)
750 {
751 private_traffic_selector_t *this;
752 chunk_t from;
753
754 this = traffic_selector_create(protocol, 0, 0, 65535);
755
756 switch (net->get_family(net))
757 {
758 case AF_INET:
759 this->type = TS_IPV4_ADDR_RANGE;
760 break;
761 case AF_INET6:
762 this->type = TS_IPV6_ADDR_RANGE;
763 break;
764 default:
765 net->destroy(net);
766 free(this);
767 return NULL;
768 }
769 from = net->get_address(net);
770 memcpy(this->from, from.ptr, from.len);
771 netbits = min(netbits, this->type == TS_IPV4_ADDR_RANGE ? 32 : 128);
772 calc_range(this, netbits);
773 if (port)
774 {
775 this->from_port = port;
776 this->to_port = port;
777 }
778 net->destroy(net);
779
780 return &this->public;
781 }
782
783 /*
784 * see header
785 */
786 traffic_selector_t *traffic_selector_create_from_string(
787 u_int8_t protocol, ts_type_t type,
788 char *from_addr, u_int16_t from_port,
789 char *to_addr, u_int16_t to_port)
790 {
791 private_traffic_selector_t *this = traffic_selector_create(protocol, type,
792 from_port, to_port);
793
794 switch (type)
795 {
796 case TS_IPV4_ADDR_RANGE:
797 if (inet_pton(AF_INET, from_addr, (struct in_addr*)this->from4) < 0)
798 {
799 free(this);
800 return NULL;
801 }
802 if (inet_pton(AF_INET, to_addr, (struct in_addr*)this->to4) < 0)
803 {
804 free(this);
805 return NULL;
806 }
807 break;
808 case TS_IPV6_ADDR_RANGE:
809 if (inet_pton(AF_INET6, from_addr, (struct in6_addr*)this->from6) < 0)
810 {
811 free(this);
812 return NULL;
813 }
814 if (inet_pton(AF_INET6, to_addr, (struct in6_addr*)this->to6) < 0)
815 {
816 free(this);
817 return NULL;
818 }
819 break;
820 }
821 calc_netbits(this);
822 return (&this->public);
823 }
824
825 /*
826 * see header
827 */
828 traffic_selector_t *traffic_selector_create_from_cidr(char *string,
829 u_int8_t protocol, u_int16_t port)
830 {
831 host_t *net;
832 int bits;
833
834 net = host_create_from_subnet(string, &bits);
835 if (net)
836 {
837 return traffic_selector_create_from_subnet(net, bits, protocol, port);
838 }
839 return NULL;
840 }
841
842 /*
843 * see header
844 */
845 traffic_selector_t *traffic_selector_create_dynamic(u_int8_t protocol,
846 u_int16_t from_port, u_int16_t to_port)
847 {
848 private_traffic_selector_t *this = traffic_selector_create(
849 protocol, TS_IPV4_ADDR_RANGE, from_port, to_port);
850
851 memset(this->from6, 0, sizeof(this->from6));
852 memset(this->to6, 0xFF, sizeof(this->to6));
853 this->netbits = 0;
854 this->dynamic = TRUE;
855
856 return &this->public;
857 }
858
859 /*
860 * see declaration
861 */
862 static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol,
863 ts_type_t type, u_int16_t from_port, u_int16_t to_port)
864 {
865 private_traffic_selector_t *this;
866
867 INIT(this,
868 .public = {
869 .get_subset = _get_subset,
870 .equals = _equals,
871 .get_from_address = _get_from_address,
872 .get_to_address = _get_to_address,
873 .get_from_port = _get_from_port,
874 .get_to_port = _get_to_port,
875 .get_type = _get_type,
876 .get_protocol = _get_protocol,
877 .is_host = _is_host,
878 .is_dynamic = _is_dynamic,
879 .is_contained_in = _is_contained_in,
880 .includes = _includes,
881 .set_address = _set_address,
882 .to_subnet = _to_subnet,
883 .clone = _clone_,
884 .destroy = _destroy,
885 },
886 .from_port = from_port,
887 .to_port = to_port,
888 .protocol = protocol,
889 .type = type,
890 );
891
892 return this;
893 }