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