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