fixed IP range to subnet conversion in ts_to_subnet()
[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 iterator_t *iterator;
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 iterator = list->create_iterator(list, TRUE);
204 while (iterator->iterate(iterator, (void**)&this))
205 {
206 /* call recursivly */
207 written += print_in_hook(dst, len, "%R ", this);
208 }
209 iterator->destroy(iterator);
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 /**
417 * Implements traffic_selector_t.get_from_address.
418 */
419 static chunk_t get_from_address(private_traffic_selector_t *this)
420 {
421 switch (this->type)
422 {
423 case TS_IPV4_ADDR_RANGE:
424 return chunk_create(this->from, sizeof(this->from4));
425 case TS_IPV6_ADDR_RANGE:
426 return chunk_create(this->from, sizeof(this->from6));
427 default:
428 return chunk_empty;
429 }
430 }
431
432 /**
433 * Implements traffic_selector_t.get_to_address.
434 */
435 static chunk_t get_to_address(private_traffic_selector_t *this)
436 {
437 switch (this->type)
438 {
439 case TS_IPV4_ADDR_RANGE:
440 return chunk_create(this->to, sizeof(this->to4));
441 case TS_IPV6_ADDR_RANGE:
442 return chunk_create(this->to, sizeof(this->to6));
443 default:
444 return chunk_empty;
445 }
446 }
447
448 /**
449 * Implements traffic_selector_t.get_from_port.
450 */
451 static u_int16_t get_from_port(private_traffic_selector_t *this)
452 {
453 return this->from_port;
454 }
455
456 /**
457 * Implements traffic_selector_t.get_to_port.
458 */
459 static u_int16_t get_to_port(private_traffic_selector_t *this)
460 {
461 return this->to_port;
462 }
463
464 /**
465 * Implements traffic_selector_t.get_type.
466 */
467 static ts_type_t get_type(private_traffic_selector_t *this)
468 {
469 return this->type;
470 }
471
472 /**
473 * Implements traffic_selector_t.get_protocol.
474 */
475 static u_int8_t get_protocol(private_traffic_selector_t *this)
476 {
477 return this->protocol;
478 }
479
480 /**
481 * Implements traffic_selector_t.is_host.
482 */
483 static bool is_host(private_traffic_selector_t *this, host_t *host)
484 {
485 if (host)
486 {
487 chunk_t addr;
488 int family = host->get_family(host);
489
490 if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
491 (family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
492 {
493 addr = host->get_address(host);
494 if (memeq(addr.ptr, this->from, addr.len) &&
495 memeq(addr.ptr, this->to, addr.len))
496 {
497 return TRUE;
498 }
499 }
500 }
501 else
502 {
503 size_t length = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
504
505 if (this->dynamic)
506 {
507 return TRUE;
508 }
509
510 if (memeq(this->from, this->to, length))
511 {
512 return TRUE;
513 }
514 }
515 return FALSE;
516 }
517
518 /**
519 * Implementation of traffic_selector_t.is_dynamic
520 */
521 static bool is_dynamic(private_traffic_selector_t *this)
522 {
523 return this->dynamic;
524 }
525
526 /**
527 * Implements traffic_selector_t.set_address.
528 */
529 static void set_address(private_traffic_selector_t *this, host_t *host)
530 {
531 if (this->dynamic)
532 {
533 this->type = host->get_family(host) == AF_INET ?
534 TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE;
535
536 if (host->is_anyaddr(host))
537 {
538 memset(this->from6, 0x00, sizeof(this->from6));
539 memset(this->to6, 0xFF, sizeof(this->to6));
540 this->netbits = 0;
541 }
542 else
543 {
544 chunk_t from = host->get_address(host);
545 memcpy(this->from, from.ptr, from.len);
546 memcpy(this->to, from.ptr, from.len);
547 this->netbits = from.len * 8;
548 }
549 }
550 }
551
552 /**
553 * Implements traffic_selector_t.is_contained_in.
554 */
555 static bool is_contained_in(private_traffic_selector_t *this,
556 private_traffic_selector_t *other)
557 {
558 private_traffic_selector_t *subset;
559 bool contained_in = FALSE;
560
561 subset = (private_traffic_selector_t*)get_subset(this, other);
562
563 if (subset)
564 {
565 if (equals(subset, this))
566 {
567 contained_in = TRUE;
568 }
569 free(subset);
570 }
571 return contained_in;
572 }
573
574 /**
575 * Implements traffic_selector_t.includes.
576 */
577 static bool includes(private_traffic_selector_t *this, host_t *host)
578 {
579 chunk_t addr;
580 int family = host->get_family(host);
581
582 if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
583 (family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
584 {
585 addr = host->get_address(host);
586
587 return memcmp(this->from, addr.ptr, addr.len) <= 0 &&
588 memcmp(this->to, addr.ptr, addr.len) >= 0;
589 }
590
591 return FALSE;
592 }
593
594 /**
595 * Implements traffic_selector_t.to_subnet.
596 */
597 static void to_subnet(private_traffic_selector_t *this, host_t **net, u_int8_t *mask)
598 {
599 /* there is no way to do this cleanly, as the address range may
600 * be anything else but a subnet. We use from_addr as subnet
601 * and try to calculate a usable subnet mask.
602 */
603 int family, non_zero_bytes;
604 u_int16_t port = 0;
605 chunk_t net_chunk;
606
607 *mask = (this->netbits == NON_SUBNET_ADDRESS_RANGE) ? calc_netbits(this)
608 : this->netbits;
609
610 switch (this->type)
611 {
612 case TS_IPV4_ADDR_RANGE:
613 family = AF_INET;
614 net_chunk.len = sizeof(this->from4);
615 break;
616 case TS_IPV6_ADDR_RANGE:
617 family = AF_INET6;
618 net_chunk.len = sizeof(this->from6);
619 break;
620 default:
621 /* unreachable */
622 return;
623 }
624
625 net_chunk.ptr = malloc(net_chunk.len);
626 memset(net_chunk.ptr, 0x00, net_chunk.len);
627 if (*mask)
628 {
629 non_zero_bytes = (*mask + 7) / 8;
630 memcpy(net_chunk.ptr, this->from, non_zero_bytes);
631 net_chunk.ptr[non_zero_bytes-1] &= 0xFF << (8 * non_zero_bytes - *mask);
632 }
633
634 if (this->to_port == this->from_port)
635 {
636 port = this->to_port;
637 }
638
639 *net = host_create_from_chunk(family, net_chunk, port);
640 chunk_free(&net_chunk);
641 }
642
643 /**
644 * Implements traffic_selector_t.clone.
645 */
646 static traffic_selector_t *clone_(private_traffic_selector_t *this)
647 {
648 private_traffic_selector_t *clone;
649
650 clone = traffic_selector_create(this->protocol, this->type,
651 this->from_port, this->to_port);
652 clone->netbits = this->netbits;
653 clone->dynamic = this->dynamic;
654
655 switch (clone->type)
656 {
657 case TS_IPV4_ADDR_RANGE:
658 memcpy(clone->from4, this->from4, sizeof(this->from4));
659 memcpy(clone->to4, this->to4, sizeof(this->to4));
660 return &clone->public;
661 case TS_IPV6_ADDR_RANGE:
662 memcpy(clone->from6, this->from6, sizeof(this->from6));
663 memcpy(clone->to6, this->to6, sizeof(this->to6));
664 return &clone->public;
665 default:
666 /* unreachable */
667 return &clone->public;
668 }
669 }
670
671 /**
672 * Implements traffic_selector_t.destroy.
673 */
674 static void destroy(private_traffic_selector_t *this)
675 {
676 free(this);
677 }
678
679 /*
680 * see header
681 */
682 traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol,
683 ts_type_t type,
684 chunk_t from, u_int16_t from_port,
685 chunk_t to, u_int16_t to_port)
686 {
687 private_traffic_selector_t *this = traffic_selector_create(protocol, type,
688 from_port, to_port);
689
690 switch (type)
691 {
692 case TS_IPV4_ADDR_RANGE:
693 if (from.len != 4 || to.len != 4)
694 {
695 free(this);
696 return NULL;
697 }
698 memcpy(this->from4, from.ptr, from.len);
699 memcpy(this->to4, to.ptr, to.len);
700 break;
701 case TS_IPV6_ADDR_RANGE:
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 default:
711 free(this);
712 return NULL;
713 }
714 calc_netbits(this);
715 return (&this->public);
716 }
717
718 /*
719 * see header
720 */
721 traffic_selector_t *traffic_selector_create_from_rfc3779_format(ts_type_t type,
722 chunk_t from, chunk_t to)
723 {
724 size_t len;
725 private_traffic_selector_t *this = traffic_selector_create(0, type, 0, 65535);
726
727 switch (type)
728 {
729 case TS_IPV4_ADDR_RANGE:
730 len = 4;
731 break;
732 case TS_IPV6_ADDR_RANGE:
733 len = 16;
734 break;
735 default:
736 free(this);
737 return NULL;
738 }
739 memset(this->from, 0x00, len);
740 memset(this->to , 0xff, len);
741
742 if (from.len > 1)
743 {
744 memcpy(this->from, from.ptr+1, from.len-1);
745 }
746 if (to.len > 1)
747 {
748 u_int8_t mask = to.ptr[0] ? (1 << to.ptr[0]) - 1 : 0;
749
750 memcpy(this->to, to.ptr+1, to.len-1);
751 this->to[to.len-2] |= mask;
752 }
753 this->netbits = chunk_equals(from, to) ? (from.len-1)*8 - from.ptr[0]
754 : NON_SUBNET_ADDRESS_RANGE;
755 return (&this->public);
756 }
757
758 /*
759 * see header
760 */
761 traffic_selector_t *traffic_selector_create_from_subnet(host_t *net,
762 u_int8_t netbits, u_int8_t protocol, u_int16_t port)
763 {
764 private_traffic_selector_t *this = traffic_selector_create(protocol, 0, 0, 65535);
765
766 switch (net->get_family(net))
767 {
768 case AF_INET:
769 {
770 chunk_t from;
771
772 this->type = TS_IPV4_ADDR_RANGE;
773 from = net->get_address(net);
774 memcpy(this->from, from.ptr, from.len);
775 if (this->from4[0] == 0)
776 {
777 /* use /0 for 0.0.0.0 */
778 this->to4[0] = ~0;
779 this->netbits = 0;
780 }
781 else
782 {
783 calc_range(this, netbits);
784 }
785 break;
786 }
787 case AF_INET6:
788 {
789 chunk_t from;
790
791 this->type = TS_IPV6_ADDR_RANGE;
792 from = net->get_address(net);
793 memcpy(this->from, from.ptr, from.len);
794 if (this->from6[0] == 0 && this->from6[1] == 0 &&
795 this->from6[2] == 0 && this->from6[3] == 0)
796 {
797 /* use /0 for ::0 */
798 this->to6[0] = ~0;
799 this->to6[1] = ~0;
800 this->to6[2] = ~0;
801 this->to6[3] = ~0;
802 this->netbits = 0;
803 }
804 else
805 {
806 calc_range(this, netbits);
807 }
808 break;
809 }
810 default:
811 {
812 net->destroy(net);
813 free(this);
814 return NULL;
815 }
816 }
817 if (port)
818 {
819 this->from_port = port;
820 this->to_port = port;
821 }
822 net->destroy(net);
823 return (&this->public);
824 }
825
826 /*
827 * see header
828 */
829 traffic_selector_t *traffic_selector_create_from_string(
830 u_int8_t protocol, ts_type_t type,
831 char *from_addr, u_int16_t from_port,
832 char *to_addr, u_int16_t to_port)
833 {
834 private_traffic_selector_t *this = traffic_selector_create(protocol, type,
835 from_port, to_port);
836
837 switch (type)
838 {
839 case TS_IPV4_ADDR_RANGE:
840 if (inet_pton(AF_INET, from_addr, (struct in_addr*)this->from4) < 0)
841 {
842 free(this);
843 return NULL;
844 }
845 if (inet_pton(AF_INET, to_addr, (struct in_addr*)this->to4) < 0)
846 {
847 free(this);
848 return NULL;
849 }
850 break;
851 case TS_IPV6_ADDR_RANGE:
852 if (inet_pton(AF_INET6, from_addr, (struct in6_addr*)this->from6) < 0)
853 {
854 free(this);
855 return NULL;
856 }
857 if (inet_pton(AF_INET6, to_addr, (struct in6_addr*)this->to6) < 0)
858 {
859 free(this);
860 return NULL;
861 }
862 break;
863 }
864 calc_netbits(this);
865 return (&this->public);
866 }
867
868 /*
869 * see header
870 */
871 traffic_selector_t *traffic_selector_create_dynamic(u_int8_t protocol,
872 u_int16_t from_port, u_int16_t to_port)
873 {
874 private_traffic_selector_t *this = traffic_selector_create(
875 protocol, TS_IPV4_ADDR_RANGE, from_port, to_port);
876
877 memset(this->from6, 0, sizeof(this->from6));
878 memset(this->to6, 0xFF, sizeof(this->to6));
879 this->netbits = 0;
880 this->dynamic = TRUE;
881
882 return &this->public;
883 }
884
885 /*
886 * see declaration
887 */
888 static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol,
889 ts_type_t type, u_int16_t from_port, u_int16_t to_port)
890 {
891 private_traffic_selector_t *this = malloc_thing(private_traffic_selector_t);
892
893 /* public functions */
894 this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset;
895 this->public.equals = (bool(*)(traffic_selector_t*,traffic_selector_t*))equals;
896 this->public.get_from_address = (chunk_t(*)(traffic_selector_t*))get_from_address;
897 this->public.get_to_address = (chunk_t(*)(traffic_selector_t*))get_to_address;
898 this->public.get_from_port = (u_int16_t(*)(traffic_selector_t*))get_from_port;
899 this->public.get_to_port = (u_int16_t(*)(traffic_selector_t*))get_to_port;
900 this->public.get_type = (ts_type_t(*)(traffic_selector_t*))get_type;
901 this->public.get_protocol = (u_int8_t(*)(traffic_selector_t*))get_protocol;
902 this->public.is_host = (bool(*)(traffic_selector_t*,host_t*))is_host;
903 this->public.is_dynamic = (bool(*)(traffic_selector_t*))is_dynamic;
904 this->public.is_contained_in = (bool(*)(traffic_selector_t*,traffic_selector_t*))is_contained_in;
905 this->public.includes = (bool(*)(traffic_selector_t*,host_t*))includes;
906 this->public.set_address = (void(*)(traffic_selector_t*,host_t*))set_address;
907 this->public.to_subnet = (void(*)(traffic_selector_t*,host_t**,u_int8_t*))to_subnet;
908 this->public.clone = (traffic_selector_t*(*)(traffic_selector_t*))clone_;
909 this->public.destroy = (void(*)(traffic_selector_t*))destroy;
910
911 this->from_port = from_port;
912 this->to_port = to_port;
913 this->protocol = protocol;
914 this->type = type;
915 this->dynamic = FALSE;
916
917 return this;
918 }
919