added support for transport mode and (experimental!) BEET mode
[strongswan.git] / src / charon / config / traffic_selector.c
1 /**
2 * @file traffic_selector.c
3 *
4 * @brief Implementation of traffic_selector_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include <arpa/inet.h>
25 #include <string.h>
26 #include <netdb.h>
27 #include <stdio.h>
28 #include <printf.h>
29
30 #include "traffic_selector.h"
31
32 #include <utils/linked_list.h>
33 #include <utils/identification.h>
34
35 ENUM(ts_type_name, TS_IPV4_ADDR_RANGE, TS_IPV6_ADDR_RANGE,
36 "TS_IPV4_ADDR_RANGE",
37 "TS_IPV6_ADDR_RANGE",
38 );
39
40 typedef struct private_traffic_selector_t private_traffic_selector_t;
41
42 /**
43 * Private data of an traffic_selector_t object
44 */
45 struct private_traffic_selector_t {
46
47 /**
48 * Public part
49 */
50 traffic_selector_t public;
51
52 /**
53 * Type of address
54 */
55 ts_type_t type;
56
57 /**
58 * IP protocol (UDP, TCP, ICMP, ...)
59 */
60 u_int8_t protocol;
61
62 /**
63 * begin of address range, network order
64 */
65 union {
66 /** dummy char for common address manipulation */
67 char from[0];
68 /** IPv4 address */
69 u_int32_t from4[1];
70 /** IPv6 address */
71 u_int32_t from6[4];
72 };
73
74 /**
75 * end of address range, network order
76 */
77 union {
78 /** dummy char for common address manipulation */
79 char to[0];
80 /** IPv4 address */
81 u_int32_t to4[1];
82 /** IPv6 address */
83 u_int32_t to6[4];
84 };
85
86 /**
87 * begin of port range
88 */
89 u_int16_t from_port;
90
91 /**
92 * end of port range
93 */
94 u_int16_t to_port;
95 };
96
97 /**
98 * calculate to "to"-address for the "from" address and a subnet size
99 */
100 static void calc_range(private_traffic_selector_t *this, u_int8_t netbits)
101 {
102 int byte;
103 size_t size = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
104
105 /* go through the from address, starting at the tail. While we
106 * have not processed the bits belonging to the host, set them to 1 on
107 * the to address. If we reach the bits for the net, copy them from "from". */
108 for (byte = size - 1; byte >=0; byte--)
109 {
110 u_char mask = 0x00;
111 int shift;
112
113 shift = (byte+1) * 8 - netbits;
114 if (shift > 0)
115 {
116 mask = 1 << shift;
117 if (mask != 0xFF)
118 {
119 mask--;
120 }
121 }
122 this->to[byte] = this->from[byte] | mask;
123 }
124 }
125
126 /**
127 * calculate to subnet size from "to"- and "from"-address
128 */
129 static u_int8_t calc_netbits(private_traffic_selector_t *this)
130 {
131 int byte, bit;
132 size_t size = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
133
134 /* go trough all bits of the addresses, begging in the front.
135 * As longer as they equal, the subnet gets larger */
136 for (byte = 0; byte < size; byte++)
137 {
138 for (bit = 7; bit >= 0; bit--)
139 {
140 if ((1<<bit & this->from[byte]) != (1<<bit & this->to[byte]))
141 {
142 return ((7 - bit) + (byte * 8));
143 }
144 }
145 }
146 /* single host, netmask is 32/128 */
147 return (size * 8);
148 }
149
150 /**
151 * internal generic constructor
152 */
153 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);
154
155 /**
156 * output handler in printf()
157 */
158 static int print(FILE *stream, const struct printf_info *info,
159 const void *const *args)
160 {
161 private_traffic_selector_t *this = *((private_traffic_selector_t**)(args[0]));
162 char addr_str[INET6_ADDRSTRLEN] = "";
163 char *serv_proto = NULL;
164 u_int8_t mask;
165 bool has_proto;
166 bool has_ports;
167 size_t written = 0;
168
169 if (this == NULL)
170 {
171 return fprintf(stream, "(null)");
172 }
173
174 if (this->type == TS_IPV4_ADDR_RANGE)
175 {
176 inet_ntop(AF_INET, &this->from4, addr_str, sizeof(addr_str));
177 }
178 else
179 {
180 inet_ntop(AF_INET6, &this->from6, addr_str, sizeof(addr_str));
181 }
182 mask = calc_netbits(this);
183
184 written += fprintf(stream, "%s/%d", addr_str, mask);
185
186 /* check if we have protocol and/or port selectors */
187 has_proto = this->protocol != 0;
188 has_ports = !(this->from_port == 0 && this->to_port == 0xFFFF);
189
190 if (!has_proto && !has_ports)
191 {
192 return written;
193 }
194
195 written += fprintf(stream, "[");
196
197 /* build protocol string */
198 if (has_proto)
199 {
200 struct protoent *proto = getprotobynumber(this->protocol);
201
202 if (proto)
203 {
204 written += fprintf(stream, "%s", proto->p_name);
205 serv_proto = proto->p_name;
206 }
207 else
208 {
209 written += fprintf(stream, "%d", this->protocol);
210 }
211 }
212
213 if (has_proto && has_ports)
214 {
215 written += fprintf(stream, "/");
216 }
217
218 /* build port string */
219 if (has_ports)
220 {
221 if (this->from_port == this->to_port)
222 {
223 struct servent *serv = getservbyport(htons(this->from_port), serv_proto);
224
225 if (serv)
226 {
227 written += fprintf(stream, "%s", serv->s_name);
228 }
229 else
230 {
231 written += fprintf(stream, "%d", this->from_port);
232 }
233 }
234 else
235 {
236 written += fprintf(stream, "%d-%d", this->from_port, this->to_port);
237 }
238 }
239
240 written += fprintf(stream, "]");
241
242 return written;
243 }
244
245 /**
246 * register printf() handlers
247 */
248 static void __attribute__ ((constructor))print_register()
249 {
250 register_printf_function(PRINTF_TRAFFIC_SELECTOR, print, arginfo_ptr);
251 }
252
253 /**
254 * implements traffic_selector_t.get_subset
255 */
256 static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_traffic_selector_t *other)
257 {
258 if (this->type == other->type && (this->protocol == other->protocol ||
259 this->protocol == 0 || other->protocol == 0))
260 {
261 u_int16_t from_port, to_port;
262 u_char *from, *to;
263 u_int8_t protocol;
264 size_t size;
265 private_traffic_selector_t *new_ts;
266
267 /* calculate the maximum port range allowed for both */
268 from_port = max(this->from_port, other->from_port);
269 to_port = min(this->to_port, other->to_port);
270 if (from_port > to_port)
271 {
272 return NULL;
273 }
274 /* select protocol, which is not zero */
275 protocol = max(this->protocol, other->protocol);
276
277 switch (this->type)
278 {
279 case TS_IPV4_ADDR_RANGE:
280 size = sizeof(this->from4);
281 break;
282 case TS_IPV6_ADDR_RANGE:
283 size = sizeof(this->from6);
284 break;
285 default:
286 return NULL;
287 }
288
289 /* get higher from-address */
290 if (memcmp(this->from, other->from, size) > 0)
291 {
292 from = this->from;
293 }
294 else
295 {
296 from = other->from;
297 }
298 /* get lower to-address */
299 if (memcmp(this->to, other->to, size) > 0)
300 {
301 to = other->to;
302 }
303 else
304 {
305 to = this->to;
306 }
307 /* if "from" > "to", we don't have a match */
308 if (memcmp(from, to, size) > 0)
309 {
310 return NULL;
311 }
312
313 /* we have a match in protocol, port, and address: return it... */
314 new_ts = traffic_selector_create(protocol, this->type, from_port, to_port);
315 new_ts->type = this->type;
316 memcpy(new_ts->from, from, size);
317 memcpy(new_ts->to, to, size);
318
319 return &new_ts->public;
320 }
321 return NULL;
322 }
323
324 /**
325 * implements traffic_selector_t.equals
326 */
327 static bool equals(private_traffic_selector_t *this, private_traffic_selector_t *other)
328 {
329 if (this->type != other->type)
330 {
331 return FALSE;
332 }
333 if (!(this->from_port == other->from_port &&
334 this->to_port == other->to_port &&
335 this->protocol == other->protocol))
336 {
337 return FALSE;
338 }
339 switch (this->type)
340 {
341 case TS_IPV4_ADDR_RANGE:
342 if (memeq(this->from4, other->from4, sizeof(this->from4)))
343 {
344 return TRUE;
345 }
346 break;
347 case TS_IPV6_ADDR_RANGE:
348 if (memeq(this->from6, other->from6, sizeof(this->from6)))
349 {
350 return TRUE;
351 }
352 break;
353 default:
354 break;
355 }
356 return FALSE;
357 }
358
359 /**
360 * Implements traffic_selector_t.get_from_address.
361 */
362 static chunk_t get_from_address(private_traffic_selector_t *this)
363 {
364 chunk_t from = chunk_empty;
365
366 switch (this->type)
367 {
368 case TS_IPV4_ADDR_RANGE:
369 {
370 from.len = sizeof(this->from4);
371 from.ptr = malloc(from.len);
372 memcpy(from.ptr, this->from4, from.len);
373 break;
374 }
375 case TS_IPV6_ADDR_RANGE:
376 {
377 from.len = sizeof(this->from6);
378 from.ptr = malloc(from.len);
379 memcpy(from.ptr, this->from6, from.len);
380 break;
381 }
382 }
383 return from;
384 }
385
386 /**
387 * Implements traffic_selector_t.get_to_address.
388 */
389 static chunk_t get_to_address(private_traffic_selector_t *this)
390 {
391 chunk_t to = chunk_empty;
392
393 switch (this->type)
394 {
395 case TS_IPV4_ADDR_RANGE:
396 {
397 to.len = sizeof(this->to4);
398 to.ptr = malloc(to.len);
399 memcpy(to.ptr, this->to4, to.len);
400 break;
401 }
402 case TS_IPV6_ADDR_RANGE:
403 {
404 to.len = sizeof(this->to6);
405 to.ptr = malloc(to.len);
406 memcpy(to.ptr, this->to6, to.len);
407 break;
408 }
409 }
410 return to;
411 }
412
413 /**
414 * Implements traffic_selector_t.get_from_port.
415 */
416 static u_int16_t get_from_port(private_traffic_selector_t *this)
417 {
418 return this->from_port;
419 }
420
421 /**
422 * Implements traffic_selector_t.get_to_port.
423 */
424 static u_int16_t get_to_port(private_traffic_selector_t *this)
425 {
426 return this->to_port;
427 }
428
429 /**
430 * Implements traffic_selector_t.get_type.
431 */
432 static ts_type_t get_type(private_traffic_selector_t *this)
433 {
434 return this->type;
435 }
436
437 /**
438 * Implements traffic_selector_t.get_protocol.
439 */
440 static u_int8_t get_protocol(private_traffic_selector_t *this)
441 {
442 return this->protocol;
443 }
444
445 /**
446 * Implements traffic_selector_t.is_host.
447 */
448 static bool is_host(private_traffic_selector_t *this, host_t *host)
449 {
450 if (host)
451 {
452 chunk_t addr;
453 int family = host->get_family(host);
454
455 if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
456 (family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
457 {
458 addr = host->get_address(host);
459 if (memeq(addr.ptr, this->from, addr.len) &&
460 memeq(addr.ptr, this->to, addr.len))
461 {
462 return TRUE;
463 }
464 }
465 }
466 else
467 {
468 size_t length = (this->type == TS_IPV4_ADDR_RANGE) ? 4 : 16;
469
470 if (memeq(this->from, this->to, length))
471 {
472 return TRUE;
473 }
474 }
475 return FALSE;
476 }
477
478 /**
479 * Implements traffic_selector_t.update_address_range.
480 */
481 static void update_address_range(private_traffic_selector_t *this, host_t *host)
482 {
483 if ((this->type == TS_IPV4_ADDR_RANGE && this->from4[0] == 0) ||
484 (this->type == TS_IPV6_ADDR_RANGE && this->from6[0] == 0 &&
485 this->from6[1] == 0 && this->from6[2] == 0 && this->from6[3] == 0))
486 {
487 this->type = host->get_family(host) == AF_INET ?
488 TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE;
489
490 chunk_t from = host->get_address(host);
491 memcpy(this->from, from.ptr, from.len);
492 memcpy(this->to, from.ptr, from.len);
493 }
494 }
495
496 /**
497 * Implements traffic_selector_t.clone.
498 */
499 static traffic_selector_t *clone_(private_traffic_selector_t *this)
500 {
501 private_traffic_selector_t *clone;
502
503 clone = traffic_selector_create(this->protocol, this->type,
504 this->from_port, this->to_port);
505 switch (clone->type)
506 {
507 case TS_IPV4_ADDR_RANGE:
508 {
509 memcpy(clone->from4, this->from4, sizeof(this->from4));
510 memcpy(clone->to4, this->to4, sizeof(this->to4));
511 return &clone->public;
512 }
513 case TS_IPV6_ADDR_RANGE:
514 {
515 memcpy(clone->from6, this->from6, sizeof(this->from6));
516 memcpy(clone->to6, this->to6, sizeof(this->to6));
517 return &clone->public;
518 }
519 default:
520 {
521 /* unreachable */
522 return &clone->public;
523 }
524 }
525 }
526
527 /**
528 * Implements traffic_selector_t.destroy.
529 */
530 static void destroy(private_traffic_selector_t *this)
531 {
532 free(this);
533 }
534
535 /*
536 * see header
537 */
538 traffic_selector_t *traffic_selector_create_from_bytes(u_int8_t protocol, ts_type_t type, chunk_t from, u_int16_t from_port, chunk_t to, u_int16_t to_port)
539 {
540 private_traffic_selector_t *this = traffic_selector_create(protocol, type, from_port, to_port);
541
542 switch (type)
543 {
544 case TS_IPV4_ADDR_RANGE:
545 {
546 if (from.len != 4 || to.len != 4)
547 {
548 free(this);
549 return NULL;
550 }
551 memcpy(this->from4, from.ptr, from.len);
552 memcpy(this->to4, to.ptr, to.len);
553 break;
554 }
555 case TS_IPV6_ADDR_RANGE:
556 {
557 if (from.len != 16 || to.len != 16)
558 {
559 free(this);
560 return NULL;
561 }
562 memcpy(this->from6, from.ptr, from.len);
563 memcpy(this->to6, to.ptr, to.len);
564 break;
565 }
566 default:
567 {
568 free(this);
569 return NULL;
570 }
571 }
572 return (&this->public);
573 }
574
575 /*
576 * see header
577 */
578 traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, u_int8_t netbits, u_int8_t protocol, u_int16_t port)
579 {
580 private_traffic_selector_t *this = traffic_selector_create(protocol, 0, 0, 65535);
581
582 switch (net->get_family(net))
583 {
584 case AF_INET:
585 {
586 chunk_t from;
587
588 this->type = TS_IPV4_ADDR_RANGE;
589 from = net->get_address(net);
590 memcpy(this->from4, from.ptr, from.len);
591 if (this->from4[0] == 0)
592 {
593 /* use /0 for 0.0.0.0 */
594 this->to4[0] = ~0;
595 }
596 else
597 {
598 calc_range(this, netbits);
599 }
600 break;
601 }
602 case AF_INET6:
603 {
604 chunk_t from;
605
606 this->type = TS_IPV6_ADDR_RANGE;
607 from = net->get_address(net);
608 memcpy(this->from6, from.ptr, from.len);
609 if (this->from6[0] == 0 && this->from6[1] == 0 &&
610 this->from6[2] == 0 && this->from6[3] == 0)
611 {
612 /* use /0 for ::0 */
613 this->to6[0] = ~0;
614 this->to6[1] = ~0;
615 this->to6[2] = ~0;
616 this->to6[3] = ~0;
617 }
618 else
619 {
620 calc_range(this, netbits);
621 }
622 break;
623 }
624 default:
625 {
626 free(this);
627 return NULL;
628 }
629 }
630 if (port)
631 {
632 this->from_port = port;
633 this->to_port = port;
634 }
635 return (&this->public);
636 }
637
638 /*
639 * see header
640 */
641 traffic_selector_t *traffic_selector_create_from_string(u_int8_t protocol, ts_type_t type, char *from_addr, u_int16_t from_port, char *to_addr, u_int16_t to_port)
642 {
643 private_traffic_selector_t *this = traffic_selector_create(protocol, type, from_port, to_port);
644
645 /* public functions */
646 this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset;
647 this->public.destroy = (void(*)(traffic_selector_t*))destroy;
648
649 this->type = type;
650 switch (type)
651 {
652 case TS_IPV4_ADDR_RANGE:
653 {
654 if (inet_pton(AF_INET, from_addr, (struct in_addr*)this->from4) < 0)
655 {
656 free(this);
657 return NULL;
658 }
659 if (inet_pton(AF_INET, to_addr, (struct in_addr*)this->to4) < 0)
660 {
661 free(this);
662 return NULL;
663 }
664 break;
665 }
666 case TS_IPV6_ADDR_RANGE:
667 {
668 if (inet_pton(AF_INET6, from_addr, (struct in6_addr*)this->from6) < 0)
669 {
670 free(this);
671 return NULL;
672 }
673 if (inet_pton(AF_INET6, to_addr, (struct in6_addr*)this->to6) < 0)
674 {
675 free(this);
676 return NULL;
677 }
678 break;
679 }
680 }
681 return (&this->public);
682 }
683
684 /*
685 * see declaration
686 */
687 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)
688 {
689 private_traffic_selector_t *this = malloc_thing(private_traffic_selector_t);
690
691 /* public functions */
692 this->public.get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset;
693 this->public.equals = (bool(*)(traffic_selector_t*,traffic_selector_t*))equals;
694 this->public.get_from_address = (chunk_t(*)(traffic_selector_t*))get_from_address;
695 this->public.get_to_address = (chunk_t(*)(traffic_selector_t*))get_to_address;
696 this->public.get_from_port = (u_int16_t(*)(traffic_selector_t*))get_from_port;
697 this->public.get_to_port = (u_int16_t(*)(traffic_selector_t*))get_to_port;
698 this->public.get_type = (ts_type_t(*)(traffic_selector_t*))get_type;
699 this->public.get_protocol = (u_int8_t(*)(traffic_selector_t*))get_protocol;
700 this->public.is_host = (bool(*)(traffic_selector_t*,host_t*))is_host;
701 this->public.update_address_range = (void(*)(traffic_selector_t*,host_t*))update_address_range;
702 this->public.clone = (traffic_selector_t*(*)(traffic_selector_t*))clone_;
703 this->public.destroy = (void(*)(traffic_selector_t*))destroy;
704
705 this->from_port = from_port;
706 this->to_port = to_port;
707 this->protocol = protocol;
708 this->type = type;
709
710 return this;
711 }