ab82c1e571f638de95122093c28c08cffdd71a11
[strongswan.git] / src / libcharon / plugins / kernel_pfroute / kernel_pfroute_net.c
1 /*
2 * Copyright (C) 2009 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include <sys/types.h>
17 #include <sys/socket.h>
18 #include <net/if.h>
19 #include <ifaddrs.h>
20 #include <net/route.h>
21 #include <unistd.h>
22 #include <errno.h>
23
24 #include "kernel_pfroute_net.h"
25
26 #include <hydra.h>
27 #include <daemon.h>
28 #include <utils/host.h>
29 #include <threading/thread.h>
30 #include <threading/mutex.h>
31 #include <utils/linked_list.h>
32 #include <processing/jobs/callback_job.h>
33 #include <processing/jobs/roam_job.h>
34
35 #ifndef HAVE_STRUCT_SOCKADDR_SA_LEN
36 #error Cannot compile this plugin on systems where 'struct sockaddr' has no sa_len member.
37 #endif
38
39 /** delay before firing roam jobs (ms) */
40 #define ROAM_DELAY 100
41
42 /** buffer size for PF_ROUTE messages */
43 #define PFROUTE_BUFFER_SIZE 4096
44
45 typedef struct addr_entry_t addr_entry_t;
46
47 /**
48 * IP address in an inface_entry_t
49 */
50 struct addr_entry_t {
51
52 /** The ip address */
53 host_t *ip;
54
55 /** virtual IP managed by us */
56 bool virtual;
57
58 /** Number of times this IP is used, if virtual */
59 u_int refcount;
60 };
61
62 /**
63 * destroy a addr_entry_t object
64 */
65 static void addr_entry_destroy(addr_entry_t *this)
66 {
67 this->ip->destroy(this->ip);
68 free(this);
69 }
70
71 typedef struct iface_entry_t iface_entry_t;
72
73 /**
74 * A network interface on this system, containing addr_entry_t's
75 */
76 struct iface_entry_t {
77
78 /** interface index */
79 int ifindex;
80
81 /** name of the interface */
82 char ifname[IFNAMSIZ];
83
84 /** interface flags, as in netdevice(7) SIOCGIFFLAGS */
85 u_int flags;
86
87 /** list of addresses as host_t */
88 linked_list_t *addrs;
89 };
90
91 /**
92 * destroy an interface entry
93 */
94 static void iface_entry_destroy(iface_entry_t *this)
95 {
96 this->addrs->destroy_function(this->addrs, (void*)addr_entry_destroy);
97 free(this);
98 }
99
100
101 typedef struct private_kernel_pfroute_net_t private_kernel_pfroute_net_t;
102
103 /**
104 * Private variables and functions of kernel_pfroute class.
105 */
106 struct private_kernel_pfroute_net_t
107 {
108 /**
109 * Public part of the kernel_pfroute_t object.
110 */
111 kernel_pfroute_net_t public;
112
113 /**
114 * mutex to lock access to various lists
115 */
116 mutex_t *mutex;
117
118 /**
119 * Cached list of interfaces and their addresses (iface_entry_t)
120 */
121 linked_list_t *ifaces;
122
123 /**
124 * job receiving PF_ROUTE events
125 */
126 callback_job_t *job;
127
128 /**
129 * mutex to lock access to the PF_ROUTE socket
130 */
131 mutex_t *mutex_pfroute;
132
133 /**
134 * PF_ROUTE socket to communicate with the kernel
135 */
136 int socket;
137
138 /**
139 * PF_ROUTE socket to receive events
140 */
141 int socket_events;
142
143 /**
144 * sequence number for messages sent to the kernel
145 */
146 int seq;
147
148 /**
149 * time of last roam job
150 */
151 timeval_t last_roam;
152 };
153
154 /**
155 * Start a roaming job. We delay it a bit and fire only one job
156 * for multiple events. Otherwise we would create too many jobs.
157 */
158 static void fire_roam_job(private_kernel_pfroute_net_t *this, bool address)
159 {
160 timeval_t now;
161
162 time_monotonic(&now);
163 if (timercmp(&now, &this->last_roam, >))
164 {
165 now.tv_usec += ROAM_DELAY * 1000;
166 while (now.tv_usec > 1000000)
167 {
168 now.tv_sec++;
169 now.tv_usec -= 1000000;
170 }
171 this->last_roam = now;
172 hydra->scheduler->schedule_job_ms(hydra->scheduler,
173 (job_t*)roam_job_create(address), ROAM_DELAY);
174 }
175 }
176
177 /**
178 * Process an RTM_*ADDR message from the kernel
179 */
180 static void process_addr(private_kernel_pfroute_net_t *this,
181 struct rt_msghdr *msg)
182 {
183 struct ifa_msghdr *ifa = (struct ifa_msghdr*)msg;
184 sockaddr_t *sockaddr = (sockaddr_t*)(ifa + 1);
185 host_t *host = NULL;
186 enumerator_t *ifaces, *addrs;
187 iface_entry_t *iface;
188 addr_entry_t *addr;
189 bool found = FALSE, changed = FALSE, roam = FALSE;
190 int i;
191
192 for (i = 1; i < (1 << RTAX_MAX); i <<= 1)
193 {
194 if (ifa->ifam_addrs & i)
195 {
196 if (RTA_IFA & i)
197 {
198 host = host_create_from_sockaddr(sockaddr);
199 break;
200 }
201 sockaddr = (sockaddr_t*)((char*)sockaddr + sockaddr->sa_len);
202 }
203 }
204
205 if (!host)
206 {
207 return;
208 }
209
210 this->mutex->lock(this->mutex);
211 ifaces = this->ifaces->create_enumerator(this->ifaces);
212 while (ifaces->enumerate(ifaces, &iface))
213 {
214 if (iface->ifindex == ifa->ifam_index)
215 {
216 addrs = iface->addrs->create_enumerator(iface->addrs);
217 while (addrs->enumerate(addrs, &addr))
218 {
219 if (host->ip_equals(host, addr->ip))
220 {
221 found = TRUE;
222 if (ifa->ifam_type == RTM_DELADDR)
223 {
224 iface->addrs->remove_at(iface->addrs, addrs);
225 if (!addr->virtual)
226 {
227 changed = TRUE;
228 DBG1(DBG_KNL, "%H disappeared from %s",
229 host, iface->ifname);
230 }
231 addr_entry_destroy(addr);
232 }
233 else if (ifa->ifam_type == RTM_NEWADDR && addr->virtual)
234 {
235 addr->refcount = 1;
236 }
237 }
238 }
239 addrs->destroy(addrs);
240
241 if (!found && ifa->ifam_type == RTM_NEWADDR)
242 {
243 changed = TRUE;
244 addr = malloc_thing(addr_entry_t);
245 addr->ip = host->clone(host);
246 addr->virtual = FALSE;
247 addr->refcount = 1;
248 iface->addrs->insert_last(iface->addrs, addr);
249 DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
250 }
251
252 if (changed && (iface->flags & IFF_UP))
253 {
254 roam = TRUE;
255 }
256 break;
257 }
258 }
259 ifaces->destroy(ifaces);
260 this->mutex->unlock(this->mutex);
261 host->destroy(host);
262
263 if (roam)
264 {
265 fire_roam_job(this, TRUE);
266 }
267 }
268
269 /**
270 * Process an RTM_IFINFO message from the kernel
271 */
272 static void process_link(private_kernel_pfroute_net_t *this,
273 struct rt_msghdr *hdr)
274 {
275 struct if_msghdr *msg = (struct if_msghdr*)hdr;
276 enumerator_t *enumerator;
277 iface_entry_t *iface;
278 bool roam = FALSE;
279
280 if (msg->ifm_flags & IFF_LOOPBACK)
281 { /* ignore loopback interfaces */
282 return;
283 }
284
285 this->mutex->lock(this->mutex);
286 enumerator = this->ifaces->create_enumerator(this->ifaces);
287 while (enumerator->enumerate(enumerator, &iface))
288 {
289 if (iface->ifindex == msg->ifm_index)
290 {
291 if (!(iface->flags & IFF_UP) && (msg->ifm_flags & IFF_UP))
292 {
293 roam = TRUE;
294 DBG1(DBG_KNL, "interface %s activated", iface->ifname);
295 }
296 else if ((iface->flags & IFF_UP) && !(msg->ifm_flags & IFF_UP))
297 {
298 roam = TRUE;
299 DBG1(DBG_KNL, "interface %s deactivated", iface->ifname);
300 }
301 iface->flags = msg->ifm_flags;
302 break;
303 }
304 }
305 enumerator->destroy(enumerator);
306 this->mutex->unlock(this->mutex);
307
308 if (roam)
309 {
310 fire_roam_job(this, TRUE);
311 }
312 }
313
314 /**
315 * Process an RTM_*ROUTE message from the kernel
316 */
317 static void process_route(private_kernel_pfroute_net_t *this,
318 struct rt_msghdr *msg)
319 {
320
321 }
322
323 /**
324 * Receives events from kernel
325 */
326 static job_requeue_t receive_events(private_kernel_pfroute_net_t *this)
327 {
328 unsigned char buf[PFROUTE_BUFFER_SIZE];
329 struct rt_msghdr *msg = (struct rt_msghdr*)buf;
330 int len;
331 bool oldstate;
332
333 oldstate = thread_cancelability(TRUE);
334 len = recvfrom(this->socket_events, buf, sizeof(buf), 0, NULL, 0);
335 thread_cancelability(oldstate);
336
337 if (len < 0)
338 {
339 switch (errno)
340 {
341 case EINTR:
342 /* interrupted, try again */
343 return JOB_REQUEUE_DIRECT;
344 case EAGAIN:
345 /* no data ready, select again */
346 return JOB_REQUEUE_DIRECT;
347 default:
348 DBG1(DBG_KNL, "unable to receive from PF_ROUTE event socket");
349 sleep(1);
350 return JOB_REQUEUE_FAIR;
351 }
352 }
353
354 if (len < sizeof(msg->rtm_msglen) || len < msg->rtm_msglen ||
355 msg->rtm_version != RTM_VERSION)
356 {
357 DBG2(DBG_KNL, "received corrupted PF_ROUTE message");
358 return JOB_REQUEUE_DIRECT;
359 }
360
361 switch (msg->rtm_type)
362 {
363 case RTM_NEWADDR:
364 case RTM_DELADDR:
365 process_addr(this, msg);
366 break;
367 case RTM_IFINFO:
368 /*case RTM_IFANNOUNCE <- what about this*/
369 process_link(this, msg);
370 break;
371 case RTM_ADD:
372 case RTM_DELETE:
373 process_route(this, msg);
374 default:
375 break;
376 }
377
378 return JOB_REQUEUE_DIRECT;
379 }
380
381
382 /** enumerator over addresses */
383 typedef struct {
384 private_kernel_pfroute_net_t* this;
385 /** whether to enumerate down interfaces */
386 bool include_down_ifaces;
387 /** whether to enumerate virtual ip addresses */
388 bool include_virtual_ips;
389 } address_enumerator_t;
390
391 /**
392 * cleanup function for address enumerator
393 */
394 static void address_enumerator_destroy(address_enumerator_t *data)
395 {
396 data->this->mutex->unlock(data->this->mutex);
397 free(data);
398 }
399
400 /**
401 * filter for addresses
402 */
403 static bool filter_addresses(address_enumerator_t *data, addr_entry_t** in, host_t** out)
404 {
405 host_t *ip;
406 if (!data->include_virtual_ips && (*in)->virtual)
407 { /* skip virtual interfaces added by us */
408 return FALSE;
409 }
410 ip = (*in)->ip;
411 if (ip->get_family(ip) == AF_INET6)
412 {
413 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ip->get_sockaddr(ip);
414 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
415 { /* skip addresses with a unusable scope */
416 return FALSE;
417 }
418 }
419 *out = ip;
420 return TRUE;
421 }
422
423 /**
424 * enumerator constructor for interfaces
425 */
426 static enumerator_t *create_iface_enumerator(iface_entry_t *iface, address_enumerator_t *data)
427 {
428 return enumerator_create_filter(iface->addrs->create_enumerator(iface->addrs),
429 (void*)filter_addresses, data, NULL);
430 }
431
432 /**
433 * filter for interfaces
434 */
435 static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in, iface_entry_t** out)
436 {
437 if (!data->include_down_ifaces && !((*in)->flags & IFF_UP))
438 { /* skip interfaces not up */
439 return FALSE;
440 }
441 *out = *in;
442 return TRUE;
443 }
444
445 /**
446 * implementation of kernel_net_t.create_address_enumerator
447 */
448 static enumerator_t *create_address_enumerator(private_kernel_pfroute_net_t *this,
449 bool include_down_ifaces, bool include_virtual_ips)
450 {
451 address_enumerator_t *data = malloc_thing(address_enumerator_t);
452 data->this = this;
453 data->include_down_ifaces = include_down_ifaces;
454 data->include_virtual_ips = include_virtual_ips;
455
456 this->mutex->lock(this->mutex);
457 return enumerator_create_nested(
458 enumerator_create_filter(this->ifaces->create_enumerator(this->ifaces),
459 (void*)filter_interfaces, data, NULL),
460 (void*)create_iface_enumerator, data, (void*)address_enumerator_destroy);
461 }
462
463 /**
464 * implementation of kernel_net_t.get_interface_name
465 */
466 static char *get_interface_name(private_kernel_pfroute_net_t *this, host_t* ip)
467 {
468 enumerator_t *ifaces, *addrs;
469 iface_entry_t *iface;
470 addr_entry_t *addr;
471 char *name = NULL;
472
473 DBG2(DBG_KNL, "getting interface name for %H", ip);
474
475 this->mutex->lock(this->mutex);
476 ifaces = this->ifaces->create_enumerator(this->ifaces);
477 while (ifaces->enumerate(ifaces, &iface))
478 {
479 addrs = iface->addrs->create_enumerator(iface->addrs);
480 while (addrs->enumerate(addrs, &addr))
481 {
482 if (ip->ip_equals(ip, addr->ip))
483 {
484 name = strdup(iface->ifname);
485 break;
486 }
487 }
488 addrs->destroy(addrs);
489 if (name)
490 {
491 break;
492 }
493 }
494 ifaces->destroy(ifaces);
495 this->mutex->unlock(this->mutex);
496
497 if (name)
498 {
499 DBG2(DBG_KNL, "%H is on interface %s", ip, name);
500 }
501 else
502 {
503 DBG2(DBG_KNL, "%H is not a local address", ip);
504 }
505 return name;
506 }
507
508 /**
509 * Implementation of kernel_net_t.get_source_addr.
510 */
511 static host_t* get_source_addr(private_kernel_pfroute_net_t *this,
512 host_t *dest, host_t *src)
513 {
514 return NULL;
515 }
516
517 /**
518 * Implementation of kernel_net_t.get_nexthop.
519 */
520 static host_t* get_nexthop(private_kernel_pfroute_net_t *this, host_t *dest)
521 {
522 return NULL;
523 }
524
525 /**
526 * Implementation of kernel_net_t.add_ip.
527 */
528 static status_t add_ip(private_kernel_pfroute_net_t *this,
529 host_t *virtual_ip, host_t *iface_ip)
530 {
531 return FAILED;
532 }
533
534 /**
535 * Implementation of kernel_net_t.del_ip.
536 */
537 static status_t del_ip(private_kernel_pfroute_net_t *this, host_t *virtual_ip)
538 {
539 return FAILED;
540 }
541
542 /**
543 * Implementation of kernel_net_t.add_route.
544 */
545 static status_t add_route(private_kernel_pfroute_net_t *this, chunk_t dst_net,
546 u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name)
547 {
548 return FAILED;
549 }
550
551 /**
552 * Implementation of kernel_net_t.del_route.
553 */
554 static status_t del_route(private_kernel_pfroute_net_t *this, chunk_t dst_net,
555 u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name)
556 {
557 return FAILED;
558 }
559
560 /**
561 * Initialize a list of local addresses.
562 */
563 static status_t init_address_list(private_kernel_pfroute_net_t *this)
564 {
565 struct ifaddrs *ifap, *ifa;
566 iface_entry_t *iface, *current;
567 addr_entry_t *addr;
568 enumerator_t *ifaces, *addrs;
569
570 DBG1(DBG_KNL, "listening on interfaces:");
571
572 if (getifaddrs(&ifap) < 0)
573 {
574 DBG1(DBG_KNL, " failed to get interfaces!");
575 return FAILED;
576 }
577
578 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
579 {
580 if (ifa->ifa_addr == NULL)
581 {
582 continue;
583 }
584 switch(ifa->ifa_addr->sa_family)
585 {
586 case AF_LINK:
587 case AF_INET:
588 case AF_INET6:
589 {
590 if (ifa->ifa_flags & IFF_LOOPBACK)
591 { /* ignore loopback interfaces */
592 continue;
593 }
594
595 iface = NULL;
596 ifaces = this->ifaces->create_enumerator(this->ifaces);
597 while (ifaces->enumerate(ifaces, &current))
598 {
599 if (streq(current->ifname, ifa->ifa_name))
600 {
601 iface = current;
602 break;
603 }
604 }
605 ifaces->destroy(ifaces);
606
607 if (!iface)
608 {
609 iface = malloc_thing(iface_entry_t);
610 memcpy(iface->ifname, ifa->ifa_name, IFNAMSIZ);
611 iface->ifindex = if_nametoindex(ifa->ifa_name);
612 iface->flags = ifa->ifa_flags;
613 iface->addrs = linked_list_create();
614 this->ifaces->insert_last(this->ifaces, iface);
615 }
616
617 if (ifa->ifa_addr->sa_family != AF_LINK)
618 {
619 addr = malloc_thing(addr_entry_t);
620 addr->ip = host_create_from_sockaddr(ifa->ifa_addr);
621 addr->virtual = FALSE;
622 addr->refcount = 1;
623 iface->addrs->insert_last(iface->addrs, addr);
624 }
625 }
626 }
627 }
628 freeifaddrs(ifap);
629
630 ifaces = this->ifaces->create_enumerator(this->ifaces);
631 while (ifaces->enumerate(ifaces, &iface))
632 {
633 if (iface->flags & IFF_UP)
634 {
635 DBG1(DBG_KNL, " %s", iface->ifname);
636 addrs = iface->addrs->create_enumerator(iface->addrs);
637 while (addrs->enumerate(addrs, (void**)&addr))
638 {
639 DBG1(DBG_KNL, " %H", addr->ip);
640 }
641 addrs->destroy(addrs);
642 }
643 }
644 ifaces->destroy(ifaces);
645
646 return SUCCESS;
647 }
648
649 /**
650 * Implementation of kernel_netlink_net_t.destroy.
651 */
652 static void destroy(private_kernel_pfroute_net_t *this)
653 {
654 if (this->job)
655 {
656 this->job->cancel(this->job);
657 }
658 if (this->socket > 0)
659 {
660 close(this->socket);
661 }
662 if (this->socket_events)
663 {
664 close(this->socket_events);
665 }
666 this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
667 this->mutex->destroy(this->mutex);
668 this->mutex_pfroute->destroy(this->mutex_pfroute);
669 free(this);
670 }
671
672 /*
673 * Described in header.
674 */
675 kernel_pfroute_net_t *kernel_pfroute_net_create()
676 {
677 private_kernel_pfroute_net_t *this = malloc_thing(private_kernel_pfroute_net_t);
678
679 /* public functions */
680 this->public.interface.get_interface = (char*(*)(kernel_net_t*,host_t*))get_interface_name;
681 this->public.interface.create_address_enumerator = (enumerator_t*(*)(kernel_net_t*,bool,bool))create_address_enumerator;
682 this->public.interface.get_source_addr = (host_t*(*)(kernel_net_t*, host_t *dest, host_t *src))get_source_addr;
683 this->public.interface.get_nexthop = (host_t*(*)(kernel_net_t*, host_t *dest))get_nexthop;
684 this->public.interface.add_ip = (status_t(*)(kernel_net_t*,host_t*,host_t*)) add_ip;
685 this->public.interface.del_ip = (status_t(*)(kernel_net_t*,host_t*)) del_ip;
686 this->public.interface.add_route = (status_t(*)(kernel_net_t*,chunk_t,u_int8_t,host_t*,host_t*,char*)) add_route;
687 this->public.interface.del_route = (status_t(*)(kernel_net_t*,chunk_t,u_int8_t,host_t*,host_t*,char*)) del_route;
688
689 this->public.interface.destroy = (void(*)(kernel_net_t*)) destroy;
690
691 /* private members */
692 this->ifaces = linked_list_create();
693 this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
694 this->mutex_pfroute = mutex_create(MUTEX_TYPE_DEFAULT);
695
696 this->seq = 0;
697 this->socket_events = 0;
698 this->job = NULL;
699
700 /* create a PF_ROUTE socket to communicate with the kernel */
701 this->socket = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
702 if (this->socket < 0)
703 {
704 DBG1(DBG_KNL, "unable to create PF_ROUTE socket");
705 destroy(this);
706 return NULL;
707 }
708
709 /* create a PF_ROUTE socket to receive events */
710 this->socket_events = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
711 if (this->socket_events < 0)
712 {
713 DBG1(DBG_KNL, "unable to create PF_ROUTE event socket");
714 destroy(this);
715 return NULL;
716 }
717
718 this->job = callback_job_create((callback_job_cb_t)receive_events,
719 this, NULL, NULL);
720 hydra->processor->queue_job(hydra->processor, (job_t*)this->job);
721
722 if (init_address_list(this) != SUCCESS)
723 {
724 DBG1(DBG_KNL, "unable to get interface list");
725 destroy(this);
726 return NULL;
727 }
728
729 return &this->public;
730 }