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