Annotation of embedaddon/strongswan/src/libstrongswan/selectors/traffic_selector.c, revision 1.1.1.1
1.1 misho 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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>