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