]> git.ipfire.org Git - people/ms/strongswan.git/blob - src/libstrongswan/selectors/traffic_selector.c
cfd2b029dbe2468934ddc56123d0dd190891cf72
[people/ms/strongswan.git] / src / libstrongswan / selectors / traffic_selector.c
1 /*
2 * Copyright (C) 2007-2017 Tobias Brunner
3 * Copyright (C) 2005-2007 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * HSR 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 <string.h>
19 #include <stdio.h>
20
21 #include "traffic_selector.h"
22
23 #include <utils/debug.h>
24 #include <utils/utils.h>
25 #include <utils/identification.h>
26 #include <collections/linked_list.h>
27
28 #define IPV4_LEN 4
29 #define IPV6_LEN 16
30 #define TS_IP_LEN(this) ({ ((this)->type == TS_IPV4_ADDR_RANGE) ? IPV4_LEN : IPV6_LEN; })
31
32 #define NON_SUBNET_ADDRESS_RANGE 255
33
34 ENUM(ts_type_name, TS_IPV4_ADDR_RANGE, TS_IPV6_ADDR_RANGE,
35 "TS_IPV4_ADDR_RANGE",
36 "TS_IPV6_ADDR_RANGE",
37 );
38
39 typedef struct private_traffic_selector_t private_traffic_selector_t;
40
41 /**
42 * Private data of an traffic_selector_t object
43 */
44 struct private_traffic_selector_t {
45
46 /**
47 * Public part
48 */
49 traffic_selector_t public;
50
51 /**
52 * Type of address
53 */
54 ts_type_t type;
55
56 /**
57 * IP protocol (UDP, TCP, ICMP, ...)
58 */
59 uint8_t protocol;
60
61 /**
62 * narrow this traffic selector to hosts external ip
63 * if set, from and to have no meaning until set_address() is called
64 */
65 bool dynamic;
66
67 /**
68 * subnet size in CIDR notation, 255 means a non-subnet address range
69 */
70 uint8_t netbits;
71
72 /**
73 * begin of address range, network order
74 */
75 char from[IPV6_LEN];
76
77 /**
78 * end of address range, network order
79 */
80 char to[IPV6_LEN];
81
82 /**
83 * begin of port range
84 */
85 uint16_t from_port;
86
87 /**
88 * end of port range
89 */
90 uint16_t to_port;
91 };
92
93 /**
94 * calculate the "to"-address for the "from" address and a subnet size
95 */
96 static void calc_range(private_traffic_selector_t *this, uint8_t netbits)
97 {
98 size_t len;
99 int bytes, bits;
100 uint8_t mask;
101
102 this->netbits = netbits;
103
104 len = TS_IP_LEN(this);
105 bytes = (netbits + 7)/8;
106 bits = (bytes * 8) - netbits;
107 mask = bits ? (1 << bits) - 1 : 0;
108
109 memcpy(this->to, this->from, bytes);
110 memset(this->from + bytes, 0x00, len - bytes);
111 memset(this->to + bytes, 0xff, len - bytes);
112 this->from[bytes-1] &= ~mask;
113 this->to[bytes-1] |= mask;
114 }
115
116 /**
117 * calculate the subnet size from the "to" and "from" addresses
118 */
119 static uint8_t calc_netbits(private_traffic_selector_t *this)
120 {
121 int byte, bit;
122 uint8_t netbits;
123 size_t size = TS_IP_LEN(this);
124 bool prefix = TRUE;
125
126 /* a perfect match results in a single address with a /32 or /128 netmask */
127 netbits = (size * 8);
128 this->netbits = netbits;
129
130 /* go through all bits of the addresses, beginning in the front.
131 * as long as they are equal, the subnet gets larger
132 */
133 for (byte = 0; byte < size; byte++)
134 {
135 for (bit = 7; bit >= 0; bit--)
136 {
137 uint8_t bitmask = 1 << bit;
138
139 if (prefix)
140 {
141 if ((bitmask & this->from[byte]) != (bitmask & this->to[byte]))
142 {
143 /* store the common prefix which might be a true subnet */
144 netbits = (7 - bit) + (byte * 8);
145 this->netbits = netbits;
146 prefix = FALSE;
147 }
148 }
149 else
150 {
151 if ((bitmask & this->from[byte]) || !(bitmask & this->to[byte]))
152 {
153 this->netbits = NON_SUBNET_ADDRESS_RANGE;
154 return netbits; /* return a pseudo subnet */
155
156 }
157 }
158 }
159 }
160 return netbits; /* return a true subnet */
161 }
162
163 /**
164 * internal generic constructor
165 */
166 static private_traffic_selector_t *traffic_selector_create(uint8_t protocol,
167 ts_type_t type, uint16_t from_port, uint16_t to_port);
168
169 /**
170 * Check if TS contains "opaque" ports
171 */
172 static bool is_opaque(private_traffic_selector_t *this)
173 {
174 return this->from_port == 0xffff && this->to_port == 0;
175 }
176
177 /**
178 * Check if TS contains "any" ports
179 */
180 static bool is_any(private_traffic_selector_t *this)
181 {
182 return this->from_port == 0 && this->to_port == 0xffff;
183 }
184
185 /**
186 * Print ICMP/ICMPv6 type and code
187 */
188 static int print_icmp(printf_hook_data_t *data, uint16_t port)
189 {
190 uint8_t type, code;
191
192 type = traffic_selector_icmp_type(port);
193 code = traffic_selector_icmp_code(port);
194 if (code)
195 {
196 return print_in_hook(data, "%d(%d)", type, code);
197 }
198 return print_in_hook(data, "%d", type);
199 }
200
201 /**
202 * Described in header.
203 */
204 int traffic_selector_printf_hook(printf_hook_data_t *data,
205 printf_hook_spec_t *spec, const void *const *args)
206 {
207 private_traffic_selector_t *this = *((private_traffic_selector_t**)(args[0]));
208 linked_list_t *list = *((linked_list_t**)(args[0]));
209 enumerator_t *enumerator;
210 char from_str[INET6_ADDRSTRLEN] = "";
211 char to_str[INET6_ADDRSTRLEN] = "";
212 char *serv_proto = NULL, *sep = "";
213 bool has_proto, has_ports;
214 size_t written = 0, len;
215 char from[IPV6_LEN], to[IPV6_LEN];
216
217 if (this == NULL)
218 {
219 return print_in_hook(data, "(null)");
220 }
221
222 if (spec->hash)
223 {
224 enumerator = list->create_enumerator(list);
225 while (enumerator->enumerate(enumerator, (void**)&this))
226 {
227 written += print_in_hook(data, "%s%R", sep, this);
228 sep = " ";
229 }
230 enumerator->destroy(enumerator);
231 return written;
232 }
233
234 len = TS_IP_LEN(this);
235 memset(from, 0, len);
236 memset(to, 0xFF, len);
237 if (this->dynamic &&
238 memeq(this->from, from, len) && memeq(this->to, to, len))
239 {
240 written += print_in_hook(data, "dynamic");
241 }
242 else
243 {
244 if (this->type == TS_IPV4_ADDR_RANGE)
245 {
246 inet_ntop(AF_INET, &this->from, from_str, sizeof(from_str));
247 }
248 else
249 {
250 inet_ntop(AF_INET6, &this->from, from_str, sizeof(from_str));
251 }
252 if (this->netbits == NON_SUBNET_ADDRESS_RANGE)
253 {
254 if (this->type == TS_IPV4_ADDR_RANGE)
255 {
256 inet_ntop(AF_INET, &this->to, to_str, sizeof(to_str));
257 }
258 else
259 {
260 inet_ntop(AF_INET6, &this->to, to_str, sizeof(to_str));
261 }
262 written += print_in_hook(data, "%s..%s", from_str, to_str);
263 }
264 else
265 {
266 written += print_in_hook(data, "%s/%d", from_str, this->netbits);
267 }
268 }
269
270 /* check if we have protocol and/or port selectors */
271 has_proto = this->protocol != 0;
272 has_ports = !is_any(this);
273
274 if (!has_proto && !has_ports)
275 {
276 return written;
277 }
278
279 written += print_in_hook(data, "[");
280
281 /* build protocol string */
282 if (has_proto)
283 {
284 struct protoent *proto = getprotobynumber(this->protocol);
285
286 if (proto)
287 {
288 written += print_in_hook(data, "%s", proto->p_name);
289 serv_proto = proto->p_name;
290 }
291 else
292 {
293 written += print_in_hook(data, "%d", this->protocol);
294 }
295 }
296 else
297 {
298 written += print_in_hook(data, "0");
299 }
300
301 /* build port string */
302 if (has_ports)
303 {
304 written += print_in_hook(data, "/");
305
306 if (this->from_port == this->to_port)
307 {
308 struct servent *serv;
309
310 if (this->protocol == IPPROTO_ICMP ||
311 this->protocol == IPPROTO_ICMPV6)
312 {
313 written += print_icmp(data, this->from_port);
314 }
315 else
316 {
317 serv = getservbyport(htons(this->from_port), serv_proto);
318 if (serv)
319 {
320 written += print_in_hook(data, "%s", serv->s_name);
321 }
322 else
323 {
324 written += print_in_hook(data, "%d", this->from_port);
325 }
326 }
327 }
328 else if (is_opaque(this))
329 {
330 written += print_in_hook(data, "OPAQUE");
331 }
332 else if (this->protocol == IPPROTO_ICMP ||
333 this->protocol == IPPROTO_ICMPV6)
334 {
335 written += print_icmp(data, this->from_port);
336 written += print_in_hook(data, "-");
337 written += print_icmp(data, this->to_port);
338 }
339 else
340 {
341 written += print_in_hook(data, "%d-%d",
342 this->from_port, this->to_port);
343 }
344 }
345
346 written += print_in_hook(data, "]");
347
348 return written;
349 }
350
351 METHOD(traffic_selector_t, get_subset, traffic_selector_t*,
352 private_traffic_selector_t *this, traffic_selector_t *other_public)
353 {
354 private_traffic_selector_t *other, *subset;
355 uint16_t from_port, to_port;
356 u_char *from, *to;
357 uint8_t protocol;
358 size_t size;
359
360 other = (private_traffic_selector_t*)other_public;
361
362 if (this->dynamic || other->dynamic)
363 { /* no set_address() applied, TS has no subset */
364 return NULL;
365 }
366
367 if (this->type != other->type)
368 {
369 return NULL;
370 }
371
372 if (this->protocol != other->protocol &&
373 this->protocol != 0 && other->protocol != 0)
374 {
375 return NULL;
376 }
377 /* select protocol, which is not zero */
378 protocol = max(this->protocol, other->protocol);
379
380 if ((is_opaque(this) && is_opaque(other)) ||
381 (is_opaque(this) && is_any(other)) ||
382 (is_opaque(other) && is_any(this)))
383 {
384 from_port = 0xffff;
385 to_port = 0;
386 }
387 else
388 {
389 /* calculate the maximum port range allowed for both */
390 from_port = max(this->from_port, other->from_port);
391 to_port = min(this->to_port, other->to_port);
392 if (from_port > to_port)
393 {
394 return NULL;
395 }
396 }
397 size = TS_IP_LEN(this);
398 /* get higher from-address */
399 if (memcmp(this->from, other->from, size) > 0)
400 {
401 from = this->from;
402 }
403 else
404 {
405 from = other->from;
406 }
407 /* get lower to-address */
408 if (memcmp(this->to, other->to, size) > 0)
409 {
410 to = other->to;
411 }
412 else
413 {
414 to = this->to;
415 }
416 /* if "from" > "to", we don't have a match */
417 if (memcmp(from, to, size) > 0)
418 {
419 return NULL;
420 }
421
422 /* we have a match in protocol, port, and address: return it... */
423 subset = traffic_selector_create(protocol, this->type, from_port, to_port);
424 memcpy(subset->from, from, size);
425 memcpy(subset->to, to, size);
426 calc_netbits(subset);
427
428 return &subset->public;
429 }
430
431 METHOD(traffic_selector_t, equals, bool,
432 private_traffic_selector_t *this, traffic_selector_t *other)
433 {
434 return traffic_selector_cmp(&this->public, other, NULL) == 0;
435 }
436
437 METHOD(traffic_selector_t, get_from_address, chunk_t,
438 private_traffic_selector_t *this)
439 {
440 return chunk_create(this->from, TS_IP_LEN(this));
441 }
442
443 METHOD(traffic_selector_t, get_to_address, chunk_t,
444 private_traffic_selector_t *this)
445 {
446 return chunk_create(this->to, TS_IP_LEN(this));
447 }
448
449 METHOD(traffic_selector_t, get_from_port, uint16_t,
450 private_traffic_selector_t *this)
451 {
452 return this->from_port;
453 }
454
455 METHOD(traffic_selector_t, get_to_port, uint16_t,
456 private_traffic_selector_t *this)
457 {
458 return this->to_port;
459 }
460
461 METHOD(traffic_selector_t, get_type, ts_type_t,
462 private_traffic_selector_t *this)
463 {
464 return this->type;
465 }
466
467 METHOD(traffic_selector_t, get_protocol, uint8_t,
468 private_traffic_selector_t *this)
469 {
470 return this->protocol;
471 }
472
473 METHOD(traffic_selector_t, is_host, bool,
474 private_traffic_selector_t *this, host_t *host)
475 {
476 if (host)
477 {
478 chunk_t addr;
479 int family = host->get_family(host);
480
481 if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
482 (family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
483 {
484 addr = host->get_address(host);
485 if (memeq(addr.ptr, this->from, addr.len) &&
486 memeq(addr.ptr, this->to, addr.len))
487 {
488 return TRUE;
489 }
490 }
491 }
492 else
493 {
494 size_t length = TS_IP_LEN(this);
495
496 if (this->dynamic)
497 {
498 return TRUE;
499 }
500
501 if (memeq(this->from, this->to, length))
502 {
503 return TRUE;
504 }
505 }
506 return FALSE;
507 }
508
509 METHOD(traffic_selector_t, is_dynamic, bool,
510 private_traffic_selector_t *this)
511 {
512 return this->dynamic;
513 }
514
515 METHOD(traffic_selector_t, set_address, void,
516 private_traffic_selector_t *this, host_t *host)
517 {
518 this->type = host->get_family(host) == AF_INET ? TS_IPV4_ADDR_RANGE
519 : TS_IPV6_ADDR_RANGE;
520
521 if (host->is_anyaddr(host))
522 {
523 memset(this->from, 0x00, sizeof(this->from));
524 memset(this->to, 0xFF, sizeof(this->to));
525 this->netbits = 0;
526 }
527 else
528 {
529 chunk_t from = host->get_address(host);
530 memcpy(this->from, from.ptr, from.len);
531 memcpy(this->to, from.ptr, from.len);
532 this->netbits = from.len * 8;
533 }
534 this->dynamic = FALSE;
535 }
536
537 METHOD(traffic_selector_t, is_contained_in, bool,
538 private_traffic_selector_t *this, 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->public))
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, uint8_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 uint16_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 = IPV4_LEN;
593 break;
594 case TS_IPV6_ADDR_RANGE:
595 family = AF_INET6;
596 net_chunk.len = IPV6_LEN;
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 size_t len = TS_IP_LEN(this);
628
629 clone = traffic_selector_create(this->protocol, this->type,
630 this->from_port, this->to_port);
631 clone->netbits = this->netbits;
632 clone->dynamic = this->dynamic;
633
634 memcpy(clone->from, this->from, len);
635 memcpy(clone->to, this->to, len);
636 return &clone->public;
637 }
638
639 METHOD(traffic_selector_t, hash, u_int,
640 private_traffic_selector_t *this, u_int hash)
641 {
642 return chunk_hash_inc(get_from_address(this),
643 chunk_hash_inc(get_to_address(this),
644 chunk_hash_inc(chunk_from_thing(this->from_port),
645 chunk_hash_inc(chunk_from_thing(this->to_port),
646 chunk_hash_inc(chunk_from_thing(this->protocol),
647 hash)))));
648 }
649
650 METHOD(traffic_selector_t, destroy, void,
651 private_traffic_selector_t *this)
652 {
653 free(this);
654 }
655
656 /**
657 * Compare two integers
658 */
659 static int compare_int(int a, int b)
660 {
661 return a - b;
662 }
663
664 /*
665 * See header
666 */
667 int traffic_selector_cmp(traffic_selector_t *a_pub, traffic_selector_t *b_pub,
668 void *opts)
669 {
670 private_traffic_selector_t *a, *b;
671 size_t len;
672 int res;
673
674 a = (private_traffic_selector_t*)a_pub;
675 b = (private_traffic_selector_t*)b_pub;
676
677 /* IPv4 before IPv6 */
678 res = compare_int(a->type, b->type);
679 if (res)
680 {
681 return res;
682 }
683 len = TS_IP_LEN(a);
684 /* lower starting subnets first */
685 res = memcmp(a->from, b->from, len);
686 if (res)
687 {
688 return res;
689 }
690 /* larger subnets first */
691 res = memcmp(b->to, a->to, len);
692 if (res)
693 {
694 return res;
695 }
696 /* lower protocols first */
697 res = compare_int(a->protocol, b->protocol);
698 if (res)
699 {
700 return res;
701 }
702 /* lower starting ports first */
703 res = compare_int(a->from_port, b->from_port);
704 if (res)
705 {
706 return res;
707 }
708 /* larger port ranges first */
709 return compare_int(b->to_port, a->to_port);
710 }
711
712 /*
713 * see header
714 */
715 traffic_selector_t *traffic_selector_create_from_bytes(uint8_t protocol,
716 ts_type_t type,
717 chunk_t from, uint16_t from_port,
718 chunk_t to, uint16_t to_port)
719 {
720 private_traffic_selector_t *this = traffic_selector_create(protocol, type,
721 from_port, to_port);
722
723 if (!this)
724 {
725 return NULL;
726 }
727 if (from.len != to.len || from.len != TS_IP_LEN(this))
728 {
729 free(this);
730 return NULL;
731 }
732 memcpy(this->from, from.ptr, from.len);
733 memcpy(this->to, to.ptr, to.len);
734 calc_netbits(this);
735 return &this->public;
736 }
737
738 /*
739 * see header
740 */
741 traffic_selector_t *traffic_selector_create_from_rfc3779_format(ts_type_t type,
742 chunk_t from, chunk_t to)
743 {
744 private_traffic_selector_t *this = traffic_selector_create(0, type, 0, 65535);
745 size_t len;
746
747 if (!this)
748 {
749 return NULL;
750 }
751 len = TS_IP_LEN(this);
752
753 memset(this->from, 0x00, len);
754 memset(this->to , 0xff, len);
755
756 if (from.len > 1)
757 {
758 memcpy(this->from, from.ptr+1, from.len-1);
759 }
760 if (to.len > 1)
761 {
762 uint8_t mask = to.ptr[0] ? (1 << to.ptr[0]) - 1 : 0;
763
764 memcpy(this->to, to.ptr+1, to.len-1);
765 this->to[to.len-2] |= mask;
766 }
767 calc_netbits(this);
768 return &this->public;
769 }
770
771 /*
772 * see header
773 */
774 traffic_selector_t *traffic_selector_create_from_subnet(host_t *net,
775 uint8_t netbits, uint8_t protocol,
776 uint16_t from_port, uint16_t to_port)
777 {
778 private_traffic_selector_t *this;
779 ts_type_t type;
780 chunk_t from;
781
782 switch (net->get_family(net))
783 {
784 case AF_INET:
785 type = TS_IPV4_ADDR_RANGE;
786 break;
787 case AF_INET6:
788 type = TS_IPV6_ADDR_RANGE;
789 break;
790 default:
791 net->destroy(net);
792 return NULL;
793 }
794
795 this = traffic_selector_create(protocol, type, from_port, to_port);
796
797 from = net->get_address(net);
798 memcpy(this->from, from.ptr, from.len);
799 netbits = min(netbits, TS_IP_LEN(this) * 8);
800 calc_range(this, netbits);
801 net->destroy(net);
802 return &this->public;
803 }
804
805 /*
806 * see header
807 */
808 traffic_selector_t *traffic_selector_create_from_string(
809 uint8_t protocol, ts_type_t type,
810 char *from_addr, uint16_t from_port,
811 char *to_addr, uint16_t to_port)
812 {
813 private_traffic_selector_t *this;
814 int family;
815
816 switch (type)
817 {
818 case TS_IPV4_ADDR_RANGE:
819 family = AF_INET;
820 break;
821 case TS_IPV6_ADDR_RANGE:
822 family = AF_INET6;
823 break;
824 default:
825 return NULL;
826 }
827
828 this = traffic_selector_create(protocol, type, from_port, to_port);
829
830 if (inet_pton(family, from_addr, this->from) != 1 ||
831 inet_pton(family, to_addr, this->to) != 1)
832 {
833 free(this);
834 return NULL;
835 }
836 calc_netbits(this);
837 return &this->public;
838 }
839
840 /*
841 * see header
842 */
843 traffic_selector_t *traffic_selector_create_from_cidr(
844 char *string, uint8_t protocol,
845 uint16_t from_port, uint16_t to_port)
846 {
847 host_t *net;
848 int bits;
849
850 net = host_create_from_subnet(string, &bits);
851 if (net)
852 {
853 return traffic_selector_create_from_subnet(net, bits, protocol,
854 from_port, to_port);
855 }
856 return NULL;
857 }
858
859 /*
860 * see header
861 */
862 traffic_selector_t *traffic_selector_create_dynamic(uint8_t protocol,
863 uint16_t from_port, uint16_t to_port)
864 {
865 private_traffic_selector_t *this = traffic_selector_create(
866 protocol, TS_IPV4_ADDR_RANGE, from_port, to_port);
867
868 memset(this->from, 0, sizeof(this->from));
869 memset(this->to, 0xFF, sizeof(this->to));
870 this->netbits = 0;
871 this->dynamic = TRUE;
872
873 return &this->public;
874 }
875
876 /*
877 * see declaration
878 */
879 static private_traffic_selector_t *traffic_selector_create(uint8_t protocol,
880 ts_type_t type, uint16_t from_port, uint16_t to_port)
881 {
882 private_traffic_selector_t *this;
883
884 /* sanity check */
885 if (type != TS_IPV4_ADDR_RANGE && type != TS_IPV6_ADDR_RANGE)
886 {
887 return NULL;
888 }
889
890 INIT(this,
891 .public = {
892 .get_subset = _get_subset,
893 .equals = _equals,
894 .get_from_address = _get_from_address,
895 .get_to_address = _get_to_address,
896 .get_from_port = _get_from_port,
897 .get_to_port = _get_to_port,
898 .get_type = _get_type,
899 .get_protocol = _get_protocol,
900 .is_host = _is_host,
901 .is_dynamic = _is_dynamic,
902 .is_contained_in = _is_contained_in,
903 .includes = _includes,
904 .set_address = _set_address,
905 .to_subnet = _to_subnet,
906 .clone = _clone_,
907 .hash = _hash,
908 .destroy = _destroy,
909 },
910 .from_port = from_port,
911 .to_port = to_port,
912 .protocol = protocol,
913 .type = type,
914 );
915 if (protocol == IPPROTO_ICMP || protocol == IPPROTO_ICMPV6)
916 {
917 this->from_port = from_port < 256 ? from_port << 8 : from_port;
918 this->to_port = to_port < 256 ? to_port << 8 : to_port;
919 }
920 return this;
921 }