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