Keep track of installed source routes in kernel-netlink plugin.
[strongswan.git] / src / libhydra / plugins / kernel_netlink / kernel_netlink_net.c
1 /*
2 * Copyright (C) 2008-2011 Tobias Brunner
3 * Copyright (C) 2005-2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 /*
18 * Copyright (C) 2010 secunet Security Networks AG
19 * Copyright (C) 2010 Thomas Egerer
20 *
21 * Permission is hereby granted, free of charge, to any person obtaining a copy
22 * of this software and associated documentation files (the "Software"), to deal
23 * in the Software without restriction, including without limitation the rights
24 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 * copies of the Software, and to permit persons to whom the Software is
26 * furnished to do so, subject to the following conditions:
27 *
28 * The above copyright notice and this permission notice shall be included in
29 * all copies or substantial portions of the Software.
30 *
31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37 * THE SOFTWARE.
38 */
39
40 #include <sys/socket.h>
41 #include <linux/netlink.h>
42 #include <linux/rtnetlink.h>
43 #include <unistd.h>
44 #include <errno.h>
45 #include <net/if.h>
46
47 #include "kernel_netlink_net.h"
48 #include "kernel_netlink_shared.h"
49
50 #include <hydra.h>
51 #include <debug.h>
52 #include <threading/thread.h>
53 #include <threading/condvar.h>
54 #include <threading/mutex.h>
55 #include <utils/linked_list.h>
56 #include <processing/jobs/callback_job.h>
57
58 /** delay before firing roam events (ms) */
59 #define ROAM_DELAY 100
60
61 typedef struct addr_entry_t addr_entry_t;
62
63 /**
64 * IP address in an inface_entry_t
65 */
66 struct addr_entry_t {
67
68 /** The ip address */
69 host_t *ip;
70
71 /** virtual IP managed by us */
72 bool virtual;
73
74 /** scope of the address */
75 u_char scope;
76
77 /** Number of times this IP is used, if virtual */
78 u_int refcount;
79 };
80
81 /**
82 * destroy a addr_entry_t object
83 */
84 static void addr_entry_destroy(addr_entry_t *this)
85 {
86 this->ip->destroy(this->ip);
87 free(this);
88 }
89
90 typedef struct iface_entry_t iface_entry_t;
91
92 /**
93 * A network interface on this system, containing addr_entry_t's
94 */
95 struct iface_entry_t {
96
97 /** interface index */
98 int ifindex;
99
100 /** name of the interface */
101 char ifname[IFNAMSIZ];
102
103 /** interface flags, as in netdevice(7) SIOCGIFFLAGS */
104 u_int flags;
105
106 /** list of addresses as host_t */
107 linked_list_t *addrs;
108 };
109
110 /**
111 * destroy an interface entry
112 */
113 static void iface_entry_destroy(iface_entry_t *this)
114 {
115 this->addrs->destroy_function(this->addrs, (void*)addr_entry_destroy);
116 free(this);
117 }
118
119 typedef struct route_entry_t route_entry_t;
120
121 /**
122 * Installed routing entry
123 */
124 struct route_entry_t {
125 /** Name of the interface the route is bound to */
126 char *if_name;
127
128 /** Source ip of the route */
129 host_t *src_ip;
130
131 /** Gateway for this route */
132 host_t *gateway;
133
134 /** Destination net */
135 chunk_t dst_net;
136
137 /** Destination net prefixlen */
138 u_int8_t prefixlen;
139 };
140
141 /**
142 * Clone a route_entry_t object.
143 */
144 static route_entry_t *route_entry_clone(route_entry_t *this)
145 {
146 route_entry_t *route;
147
148 INIT(route,
149 .if_name = strdup(this->if_name),
150 .src_ip = this->src_ip->clone(this->src_ip),
151 .gateway = this->gateway->clone(this->gateway),
152 .dst_net = chunk_clone(this->dst_net),
153 .prefixlen = this->prefixlen,
154 );
155 return route;
156 }
157
158 /**
159 * Destroy a route_entry_t object
160 */
161 static void route_entry_destroy(route_entry_t *this)
162 {
163 free(this->if_name);
164 DESTROY_IF(this->src_ip);
165 DESTROY_IF(this->gateway);
166 chunk_free(&this->dst_net);
167 free(this);
168 }
169
170 /**
171 * Hash a route_entry_t object
172 */
173 static u_int route_entry_hash(route_entry_t *this)
174 {
175 return chunk_hash_inc(chunk_from_thing(this->prefixlen),
176 chunk_hash(this->dst_net));
177 }
178
179 /**
180 * Compare two route_entry_t objects
181 */
182 static bool route_entry_equals(route_entry_t *a, route_entry_t *b)
183 {
184 return a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
185 a->src_ip->equals(a->src_ip, b->src_ip) &&
186 a->gateway->equals(a->gateway, b->gateway) &&
187 chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen;
188 }
189
190 typedef struct private_kernel_netlink_net_t private_kernel_netlink_net_t;
191
192 /**
193 * Private variables and functions of kernel_netlink_net class.
194 */
195 struct private_kernel_netlink_net_t {
196 /**
197 * Public part of the kernel_netlink_net_t object.
198 */
199 kernel_netlink_net_t public;
200
201 /**
202 * mutex to lock access to various lists
203 */
204 mutex_t *mutex;
205
206 /**
207 * condition variable to signal virtual IP add/removal
208 */
209 condvar_t *condvar;
210
211 /**
212 * Cached list of interfaces and its addresses (iface_entry_t)
213 */
214 linked_list_t *ifaces;
215
216 /**
217 * job receiving netlink events
218 */
219 callback_job_t *job;
220
221 /**
222 * netlink rt socket (routing)
223 */
224 netlink_socket_t *socket;
225
226 /**
227 * Netlink rt socket to receive address change events
228 */
229 int socket_events;
230
231 /**
232 * time of the last roam event
233 */
234 timeval_t last_roam;
235
236 /**
237 * routing table to install routes
238 */
239 int routing_table;
240
241 /**
242 * priority of used routing table
243 */
244 int routing_table_prio;
245
246 /**
247 * installed routes
248 */
249 hashtable_t *routes;
250
251 /**
252 * whether to react to RTM_NEWROUTE or RTM_DELROUTE events
253 */
254 bool process_route;
255
256 /**
257 * whether to actually install virtual IPs
258 */
259 bool install_virtual_ip;
260
261 /**
262 * list with routing tables to be excluded from route lookup
263 */
264 linked_list_t *rt_exclude;
265 };
266
267 /**
268 * get the refcount of a virtual ip
269 */
270 static int get_vip_refcount(private_kernel_netlink_net_t *this, host_t* ip)
271 {
272 enumerator_t *ifaces, *addrs;
273 iface_entry_t *iface;
274 addr_entry_t *addr;
275 int refcount = 0;
276
277 ifaces = this->ifaces->create_enumerator(this->ifaces);
278 while (ifaces->enumerate(ifaces, (void**)&iface))
279 {
280 addrs = iface->addrs->create_enumerator(iface->addrs);
281 while (addrs->enumerate(addrs, (void**)&addr))
282 {
283 if (addr->virtual && (iface->flags & IFF_UP) &&
284 ip->ip_equals(ip, addr->ip))
285 {
286 refcount = addr->refcount;
287 break;
288 }
289 }
290 addrs->destroy(addrs);
291 if (refcount)
292 {
293 break;
294 }
295 }
296 ifaces->destroy(ifaces);
297
298 return refcount;
299 }
300
301 /**
302 * get the first non-virtual ip address on the given interface.
303 * returned host is a clone, has to be freed by caller.
304 */
305 static host_t *get_interface_address(private_kernel_netlink_net_t *this,
306 int ifindex, int family)
307 {
308 enumerator_t *ifaces, *addrs;
309 iface_entry_t *iface;
310 addr_entry_t *addr;
311 host_t *ip = NULL;
312
313 this->mutex->lock(this->mutex);
314 ifaces = this->ifaces->create_enumerator(this->ifaces);
315 while (ifaces->enumerate(ifaces, &iface))
316 {
317 if (iface->ifindex == ifindex)
318 {
319 addrs = iface->addrs->create_enumerator(iface->addrs);
320 while (addrs->enumerate(addrs, &addr))
321 {
322 if (!addr->virtual && addr->ip->get_family(addr->ip) == family)
323 {
324 ip = addr->ip->clone(addr->ip);
325 break;
326 }
327 }
328 addrs->destroy(addrs);
329 break;
330 }
331 }
332 ifaces->destroy(ifaces);
333 this->mutex->unlock(this->mutex);
334 return ip;
335 }
336
337 /**
338 * callback function that raises the delayed roam event
339 */
340 static job_requeue_t roam_event(uintptr_t address)
341 {
342 hydra->kernel_interface->roam(hydra->kernel_interface, address != 0);
343 return JOB_REQUEUE_NONE;
344 }
345
346 /**
347 * fire a roaming event. we delay it for a bit and fire only one event
348 * for multiple calls. otherwise we would create too many events.
349 */
350 static void fire_roam_event(private_kernel_netlink_net_t *this, bool address)
351 {
352 timeval_t now;
353 job_t *job;
354
355 time_monotonic(&now);
356 if (timercmp(&now, &this->last_roam, >))
357 {
358 now.tv_usec += ROAM_DELAY * 1000;
359 while (now.tv_usec > 1000000)
360 {
361 now.tv_sec++;
362 now.tv_usec -= 1000000;
363 }
364 this->last_roam = now;
365
366 job = (job_t*)callback_job_create((callback_job_cb_t)roam_event,
367 (void*)(uintptr_t)(address ? 1 : 0),
368 NULL, NULL);
369 lib->scheduler->schedule_job_ms(lib->scheduler, job, ROAM_DELAY);
370 }
371 }
372
373 /**
374 * process RTM_NEWLINK/RTM_DELLINK from kernel
375 */
376 static void process_link(private_kernel_netlink_net_t *this,
377 struct nlmsghdr *hdr, bool event)
378 {
379 struct ifinfomsg* msg = (struct ifinfomsg*)(NLMSG_DATA(hdr));
380 struct rtattr *rta = IFLA_RTA(msg);
381 size_t rtasize = IFLA_PAYLOAD (hdr);
382 enumerator_t *enumerator;
383 iface_entry_t *current, *entry = NULL;
384 char *name = NULL;
385 bool update = FALSE;
386
387 while(RTA_OK(rta, rtasize))
388 {
389 switch (rta->rta_type)
390 {
391 case IFLA_IFNAME:
392 name = RTA_DATA(rta);
393 break;
394 }
395 rta = RTA_NEXT(rta, rtasize);
396 }
397 if (!name)
398 {
399 name = "(unknown)";
400 }
401
402 this->mutex->lock(this->mutex);
403 switch (hdr->nlmsg_type)
404 {
405 case RTM_NEWLINK:
406 {
407 if (msg->ifi_flags & IFF_LOOPBACK)
408 { /* ignore loopback interfaces */
409 break;
410 }
411 enumerator = this->ifaces->create_enumerator(this->ifaces);
412 while (enumerator->enumerate(enumerator, &current))
413 {
414 if (current->ifindex == msg->ifi_index)
415 {
416 entry = current;
417 break;
418 }
419 }
420 enumerator->destroy(enumerator);
421 if (!entry)
422 {
423 entry = malloc_thing(iface_entry_t);
424 entry->ifindex = msg->ifi_index;
425 entry->flags = 0;
426 entry->addrs = linked_list_create();
427 this->ifaces->insert_last(this->ifaces, entry);
428 }
429 strncpy(entry->ifname, name, IFNAMSIZ);
430 entry->ifname[IFNAMSIZ-1] = '\0';
431 if (event)
432 {
433 if (!(entry->flags & IFF_UP) && (msg->ifi_flags & IFF_UP))
434 {
435 update = TRUE;
436 DBG1(DBG_KNL, "interface %s activated", name);
437 }
438 if ((entry->flags & IFF_UP) && !(msg->ifi_flags & IFF_UP))
439 {
440 update = TRUE;
441 DBG1(DBG_KNL, "interface %s deactivated", name);
442 }
443 }
444 entry->flags = msg->ifi_flags;
445 break;
446 }
447 case RTM_DELLINK:
448 {
449 enumerator = this->ifaces->create_enumerator(this->ifaces);
450 while (enumerator->enumerate(enumerator, &current))
451 {
452 if (current->ifindex == msg->ifi_index)
453 {
454 if (event)
455 {
456 update = TRUE;
457 DBG1(DBG_KNL, "interface %s deleted", current->ifname);
458 }
459 this->ifaces->remove_at(this->ifaces, enumerator);
460 iface_entry_destroy(current);
461 break;
462 }
463 }
464 enumerator->destroy(enumerator);
465 break;
466 }
467 }
468 this->mutex->unlock(this->mutex);
469
470 /* send an update to all IKE_SAs */
471 if (update && event)
472 {
473 fire_roam_event(this, TRUE);
474 }
475 }
476
477 /**
478 * process RTM_NEWADDR/RTM_DELADDR from kernel
479 */
480 static void process_addr(private_kernel_netlink_net_t *this,
481 struct nlmsghdr *hdr, bool event)
482 {
483 struct ifaddrmsg* msg = (struct ifaddrmsg*)(NLMSG_DATA(hdr));
484 struct rtattr *rta = IFA_RTA(msg);
485 size_t rtasize = IFA_PAYLOAD (hdr);
486 host_t *host = NULL;
487 enumerator_t *ifaces, *addrs;
488 iface_entry_t *iface;
489 addr_entry_t *addr;
490 chunk_t local = chunk_empty, address = chunk_empty;
491 bool update = FALSE, found = FALSE, changed = FALSE;
492
493 while(RTA_OK(rta, rtasize))
494 {
495 switch (rta->rta_type)
496 {
497 case IFA_LOCAL:
498 local.ptr = RTA_DATA(rta);
499 local.len = RTA_PAYLOAD(rta);
500 break;
501 case IFA_ADDRESS:
502 address.ptr = RTA_DATA(rta);
503 address.len = RTA_PAYLOAD(rta);
504 break;
505 }
506 rta = RTA_NEXT(rta, rtasize);
507 }
508
509 /* For PPP interfaces, we need the IFA_LOCAL address,
510 * IFA_ADDRESS is the peers address. But IFA_LOCAL is
511 * not included in all cases (IPv6?), so fallback to IFA_ADDRESS. */
512 if (local.ptr)
513 {
514 host = host_create_from_chunk(msg->ifa_family, local, 0);
515 }
516 else if (address.ptr)
517 {
518 host = host_create_from_chunk(msg->ifa_family, address, 0);
519 }
520
521 if (host == NULL)
522 { /* bad family? */
523 return;
524 }
525
526 this->mutex->lock(this->mutex);
527 ifaces = this->ifaces->create_enumerator(this->ifaces);
528 while (ifaces->enumerate(ifaces, &iface))
529 {
530 if (iface->ifindex == msg->ifa_index)
531 {
532 addrs = iface->addrs->create_enumerator(iface->addrs);
533 while (addrs->enumerate(addrs, &addr))
534 {
535 if (host->ip_equals(host, addr->ip))
536 {
537 found = TRUE;
538 if (hdr->nlmsg_type == RTM_DELADDR)
539 {
540 iface->addrs->remove_at(iface->addrs, addrs);
541 if (!addr->virtual)
542 {
543 changed = TRUE;
544 DBG1(DBG_KNL, "%H disappeared from %s",
545 host, iface->ifname);
546 }
547 addr_entry_destroy(addr);
548 }
549 else if (hdr->nlmsg_type == RTM_NEWADDR && addr->virtual)
550 {
551 addr->refcount = 1;
552 }
553 }
554 }
555 addrs->destroy(addrs);
556
557 if (hdr->nlmsg_type == RTM_NEWADDR)
558 {
559 if (!found)
560 {
561 found = TRUE;
562 changed = TRUE;
563 addr = malloc_thing(addr_entry_t);
564 addr->ip = host->clone(host);
565 addr->virtual = FALSE;
566 addr->refcount = 1;
567 addr->scope = msg->ifa_scope;
568
569 iface->addrs->insert_last(iface->addrs, addr);
570 if (event)
571 {
572 DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
573 }
574 }
575 }
576 if (found && (iface->flags & IFF_UP))
577 {
578 update = TRUE;
579 }
580 break;
581 }
582 }
583 ifaces->destroy(ifaces);
584 this->mutex->unlock(this->mutex);
585 host->destroy(host);
586
587 /* send an update to all IKE_SAs */
588 if (update && event && changed)
589 {
590 fire_roam_event(this, TRUE);
591 }
592 }
593
594 /**
595 * process RTM_NEWROUTE and RTM_DELROUTE from kernel
596 */
597 static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *hdr)
598 {
599 struct rtmsg* msg = (struct rtmsg*)(NLMSG_DATA(hdr));
600 struct rtattr *rta = RTM_RTA(msg);
601 size_t rtasize = RTM_PAYLOAD(hdr);
602 u_int32_t rta_oif = 0;
603 host_t *host = NULL;
604
605 /* ignore routes added by us or in the local routing table (local addrs) */
606 if (msg->rtm_table && (msg->rtm_table == this->routing_table ||
607 msg->rtm_table == RT_TABLE_LOCAL))
608 {
609 return;
610 }
611
612 while (RTA_OK(rta, rtasize))
613 {
614 switch (rta->rta_type)
615 {
616 case RTA_PREFSRC:
617 DESTROY_IF(host);
618 host = host_create_from_chunk(msg->rtm_family,
619 chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)), 0);
620 break;
621 case RTA_OIF:
622 if (RTA_PAYLOAD(rta) == sizeof(rta_oif))
623 {
624 rta_oif = *(u_int32_t*)RTA_DATA(rta);
625 }
626 break;
627 }
628 rta = RTA_NEXT(rta, rtasize);
629 }
630 if (!host && rta_oif)
631 {
632 host = get_interface_address(this, rta_oif, msg->rtm_family);
633 }
634 if (host)
635 {
636 this->mutex->lock(this->mutex);
637 if (!get_vip_refcount(this, host))
638 { /* ignore routes added for virtual IPs */
639 fire_roam_event(this, FALSE);
640 }
641 this->mutex->unlock(this->mutex);
642 host->destroy(host);
643 }
644 }
645
646 /**
647 * Receives events from kernel
648 */
649 static job_requeue_t receive_events(private_kernel_netlink_net_t *this)
650 {
651 char response[1024];
652 struct nlmsghdr *hdr = (struct nlmsghdr*)response;
653 struct sockaddr_nl addr;
654 socklen_t addr_len = sizeof(addr);
655 int len;
656 bool oldstate;
657
658 oldstate = thread_cancelability(TRUE);
659 len = recvfrom(this->socket_events, response, sizeof(response), 0,
660 (struct sockaddr*)&addr, &addr_len);
661 thread_cancelability(oldstate);
662
663 if (len < 0)
664 {
665 switch (errno)
666 {
667 case EINTR:
668 /* interrupted, try again */
669 return JOB_REQUEUE_DIRECT;
670 case EAGAIN:
671 /* no data ready, select again */
672 return JOB_REQUEUE_DIRECT;
673 default:
674 DBG1(DBG_KNL, "unable to receive from rt event socket");
675 sleep(1);
676 return JOB_REQUEUE_FAIR;
677 }
678 }
679
680 if (addr.nl_pid != 0)
681 { /* not from kernel. not interested, try another one */
682 return JOB_REQUEUE_DIRECT;
683 }
684
685 while (NLMSG_OK(hdr, len))
686 {
687 /* looks good so far, dispatch netlink message */
688 switch (hdr->nlmsg_type)
689 {
690 case RTM_NEWADDR:
691 case RTM_DELADDR:
692 process_addr(this, hdr, TRUE);
693 this->condvar->broadcast(this->condvar);
694 break;
695 case RTM_NEWLINK:
696 case RTM_DELLINK:
697 process_link(this, hdr, TRUE);
698 this->condvar->broadcast(this->condvar);
699 break;
700 case RTM_NEWROUTE:
701 case RTM_DELROUTE:
702 if (this->process_route)
703 {
704 process_route(this, hdr);
705 }
706 break;
707 default:
708 break;
709 }
710 hdr = NLMSG_NEXT(hdr, len);
711 }
712 return JOB_REQUEUE_DIRECT;
713 }
714
715 /** enumerator over addresses */
716 typedef struct {
717 private_kernel_netlink_net_t* this;
718 /** whether to enumerate down interfaces */
719 bool include_down_ifaces;
720 /** whether to enumerate virtual ip addresses */
721 bool include_virtual_ips;
722 } address_enumerator_t;
723
724 /**
725 * cleanup function for address enumerator
726 */
727 static void address_enumerator_destroy(address_enumerator_t *data)
728 {
729 data->this->mutex->unlock(data->this->mutex);
730 free(data);
731 }
732
733 /**
734 * filter for addresses
735 */
736 static bool filter_addresses(address_enumerator_t *data,
737 addr_entry_t** in, host_t** out)
738 {
739 if (!data->include_virtual_ips && (*in)->virtual)
740 { /* skip virtual interfaces added by us */
741 return FALSE;
742 }
743 if ((*in)->scope >= RT_SCOPE_LINK)
744 { /* skip addresses with a unusable scope */
745 return FALSE;
746 }
747 *out = (*in)->ip;
748 return TRUE;
749 }
750
751 /**
752 * enumerator constructor for interfaces
753 */
754 static enumerator_t *create_iface_enumerator(iface_entry_t *iface,
755 address_enumerator_t *data)
756 {
757 return enumerator_create_filter(
758 iface->addrs->create_enumerator(iface->addrs),
759 (void*)filter_addresses, data, NULL);
760 }
761
762 /**
763 * filter for interfaces
764 */
765 static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in,
766 iface_entry_t** out)
767 {
768 if (!data->include_down_ifaces && !((*in)->flags & IFF_UP))
769 { /* skip interfaces not up */
770 return FALSE;
771 }
772 *out = *in;
773 return TRUE;
774 }
775
776 METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
777 private_kernel_netlink_net_t *this,
778 bool include_down_ifaces, bool include_virtual_ips)
779 {
780 address_enumerator_t *data = malloc_thing(address_enumerator_t);
781 data->this = this;
782 data->include_down_ifaces = include_down_ifaces;
783 data->include_virtual_ips = include_virtual_ips;
784
785 this->mutex->lock(this->mutex);
786 return enumerator_create_nested(
787 enumerator_create_filter(
788 this->ifaces->create_enumerator(this->ifaces),
789 (void*)filter_interfaces, data, NULL),
790 (void*)create_iface_enumerator, data,
791 (void*)address_enumerator_destroy);
792 }
793
794 METHOD(kernel_net_t, get_interface_name, char*,
795 private_kernel_netlink_net_t *this, host_t* ip)
796 {
797 enumerator_t *ifaces, *addrs;
798 iface_entry_t *iface;
799 addr_entry_t *addr;
800 char *name = NULL;
801
802 DBG2(DBG_KNL, "getting interface name for %H", ip);
803
804 this->mutex->lock(this->mutex);
805 ifaces = this->ifaces->create_enumerator(this->ifaces);
806 while (ifaces->enumerate(ifaces, &iface))
807 {
808 addrs = iface->addrs->create_enumerator(iface->addrs);
809 while (addrs->enumerate(addrs, &addr))
810 {
811 if (ip->ip_equals(ip, addr->ip))
812 {
813 name = strdup(iface->ifname);
814 break;
815 }
816 }
817 addrs->destroy(addrs);
818 if (name)
819 {
820 break;
821 }
822 }
823 ifaces->destroy(ifaces);
824 this->mutex->unlock(this->mutex);
825
826 if (name)
827 {
828 DBG2(DBG_KNL, "%H is on interface %s", ip, name);
829 }
830 else
831 {
832 DBG2(DBG_KNL, "%H is not a local address", ip);
833 }
834 return name;
835 }
836
837 /**
838 * get the index of an interface by name
839 */
840 static int get_interface_index(private_kernel_netlink_net_t *this, char* name)
841 {
842 enumerator_t *ifaces;
843 iface_entry_t *iface;
844 int ifindex = 0;
845
846 DBG2(DBG_KNL, "getting iface index for %s", name);
847
848 this->mutex->lock(this->mutex);
849 ifaces = this->ifaces->create_enumerator(this->ifaces);
850 while (ifaces->enumerate(ifaces, &iface))
851 {
852 if (streq(name, iface->ifname))
853 {
854 ifindex = iface->ifindex;
855 break;
856 }
857 }
858 ifaces->destroy(ifaces);
859 this->mutex->unlock(this->mutex);
860
861 if (ifindex == 0)
862 {
863 DBG1(DBG_KNL, "unable to get interface index for %s", name);
864 }
865 return ifindex;
866 }
867
868 /**
869 * Check if an interface with a given index is up
870 */
871 static bool is_interface_up(private_kernel_netlink_net_t *this, int index)
872 {
873 enumerator_t *ifaces;
874 iface_entry_t *iface;
875 /* default to TRUE for interface we do not monitor (e.g. lo) */
876 bool up = TRUE;
877
878 ifaces = this->ifaces->create_enumerator(this->ifaces);
879 while (ifaces->enumerate(ifaces, &iface))
880 {
881 if (iface->ifindex == index)
882 {
883 up = iface->flags & IFF_UP;
884 break;
885 }
886 }
887 ifaces->destroy(ifaces);
888 return up;
889 }
890
891 /**
892 * check if an address (chunk) addr is in subnet (net with net_len net bits)
893 */
894 static bool addr_in_subnet(chunk_t addr, chunk_t net, int net_len)
895 {
896 static const u_char mask[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
897 int byte = 0;
898
899 if (net_len == 0)
900 { /* any address matches a /0 network */
901 return TRUE;
902 }
903 if (addr.len != net.len || net_len > 8 * net.len )
904 {
905 return FALSE;
906 }
907 /* scan through all bytes in network order */
908 while (net_len > 0)
909 {
910 if (net_len < 8)
911 {
912 return (mask[net_len] & addr.ptr[byte]) == (mask[net_len] & net.ptr[byte]);
913 }
914 else
915 {
916 if (addr.ptr[byte] != net.ptr[byte])
917 {
918 return FALSE;
919 }
920 byte++;
921 net_len -= 8;
922 }
923 }
924 return TRUE;
925 }
926
927 /**
928 * Get a route: If "nexthop", the nexthop is returned. source addr otherwise.
929 */
930 static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
931 bool nexthop, host_t *candidate)
932 {
933 netlink_buf_t request;
934 struct nlmsghdr *hdr, *out, *current;
935 struct rtmsg *msg;
936 chunk_t chunk;
937 size_t len;
938 int best = -1;
939 enumerator_t *enumerator;
940 host_t *src = NULL, *gtw = NULL;
941
942 DBG2(DBG_KNL, "getting address to reach %H", dest);
943
944 memset(&request, 0, sizeof(request));
945
946 hdr = (struct nlmsghdr*)request;
947 hdr->nlmsg_flags = NLM_F_REQUEST;
948 if (dest->get_family(dest) == AF_INET)
949 {
950 /* We dump all addresses for IPv4, as we want to ignore IPsec specific
951 * routes installed by us. But the kernel does not return source
952 * addresses in a IPv6 dump, so fall back to get() for v6 routes. */
953 hdr->nlmsg_flags |= NLM_F_ROOT | NLM_F_DUMP;
954 }
955 hdr->nlmsg_type = RTM_GETROUTE;
956 hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
957
958 msg = (struct rtmsg*)NLMSG_DATA(hdr);
959 msg->rtm_family = dest->get_family(dest);
960 if (candidate)
961 {
962 chunk = candidate->get_address(candidate);
963 netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request));
964 }
965 chunk = dest->get_address(dest);
966 netlink_add_attribute(hdr, RTA_DST, chunk, sizeof(request));
967
968 if (this->socket->send(this->socket, hdr, &out, &len) != SUCCESS)
969 {
970 DBG1(DBG_KNL, "getting address to %H failed", dest);
971 return NULL;
972 }
973 this->mutex->lock(this->mutex);
974
975 for (current = out; NLMSG_OK(current, len);
976 current = NLMSG_NEXT(current, len))
977 {
978 switch (current->nlmsg_type)
979 {
980 case NLMSG_DONE:
981 break;
982 case RTM_NEWROUTE:
983 {
984 struct rtattr *rta;
985 size_t rtasize;
986 chunk_t rta_gtw, rta_src, rta_dst;
987 u_int32_t rta_oif = 0, rta_table;
988 host_t *new_src, *new_gtw;
989 bool cont = FALSE;
990 uintptr_t table;
991
992 rta_gtw = rta_src = rta_dst = chunk_empty;
993 msg = (struct rtmsg*)(NLMSG_DATA(current));
994 rta = RTM_RTA(msg);
995 rtasize = RTM_PAYLOAD(current);
996 rta_table = msg->rtm_table;
997 while (RTA_OK(rta, rtasize))
998 {
999 switch (rta->rta_type)
1000 {
1001 case RTA_PREFSRC:
1002 rta_src = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
1003 break;
1004 case RTA_GATEWAY:
1005 rta_gtw = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
1006 break;
1007 case RTA_DST:
1008 rta_dst = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
1009 break;
1010 case RTA_OIF:
1011 if (RTA_PAYLOAD(rta) == sizeof(rta_oif))
1012 {
1013 rta_oif = *(u_int32_t*)RTA_DATA(rta);
1014 }
1015 break;
1016 #ifdef HAVE_RTA_TABLE
1017 case RTA_TABLE:
1018 if (RTA_PAYLOAD(rta) == sizeof(rta_table))
1019 {
1020 rta_table = *(u_int32_t*)RTA_DATA(rta);
1021 }
1022 break;
1023 #endif /* HAVE_RTA_TABLE*/
1024 }
1025 rta = RTA_NEXT(rta, rtasize);
1026 }
1027 if (msg->rtm_dst_len <= best)
1028 { /* not better than a previous one */
1029 continue;
1030 }
1031 enumerator = this->rt_exclude->create_enumerator(this->rt_exclude);
1032 while (enumerator->enumerate(enumerator, &table))
1033 {
1034 if (table == rta_table)
1035 {
1036 cont = TRUE;
1037 break;
1038 }
1039 }
1040 enumerator->destroy(enumerator);
1041 if (cont)
1042 {
1043 continue;
1044 }
1045 if (this->routing_table != 0 &&
1046 rta_table == this->routing_table)
1047 { /* route is from our own ipsec routing table */
1048 continue;
1049 }
1050 if (rta_oif && !is_interface_up(this, rta_oif))
1051 { /* interface is down */
1052 continue;
1053 }
1054 if (!addr_in_subnet(chunk, rta_dst, msg->rtm_dst_len))
1055 { /* route destination does not contain dest */
1056 continue;
1057 }
1058
1059 if (nexthop)
1060 {
1061 /* nexthop lookup, return gateway if any */
1062 DESTROY_IF(gtw);
1063 gtw = host_create_from_chunk(msg->rtm_family, rta_gtw, 0);
1064 best = msg->rtm_dst_len;
1065 continue;
1066 }
1067 if (rta_src.ptr)
1068 { /* got a source address */
1069 new_src = host_create_from_chunk(msg->rtm_family, rta_src, 0);
1070 if (new_src)
1071 {
1072 if (get_vip_refcount(this, new_src))
1073 { /* skip source address if it is installed by us */
1074 new_src->destroy(new_src);
1075 }
1076 else
1077 {
1078 DESTROY_IF(src);
1079 src = new_src;
1080 best = msg->rtm_dst_len;
1081 }
1082 }
1083 continue;
1084 }
1085 if (rta_oif)
1086 { /* no src or gtw, but an interface. Get address from it. */
1087 new_src = get_interface_address(this, rta_oif,
1088 msg->rtm_family);
1089 if (new_src)
1090 {
1091 DESTROY_IF(src);
1092 src = new_src;
1093 best = msg->rtm_dst_len;
1094 }
1095 continue;
1096 }
1097 if (rta_gtw.ptr)
1098 { /* no source, but a gateway. Lookup source to reach gtw. */
1099 new_gtw = host_create_from_chunk(msg->rtm_family, rta_gtw, 0);
1100 new_src = get_route(this, new_gtw, FALSE, candidate);
1101 new_gtw->destroy(new_gtw);
1102 if (new_src)
1103 {
1104 DESTROY_IF(src);
1105 src = new_src;
1106 best = msg->rtm_dst_len;
1107 }
1108 continue;
1109 }
1110 continue;
1111 }
1112 default:
1113 continue;
1114 }
1115 break;
1116 }
1117 free(out);
1118 this->mutex->unlock(this->mutex);
1119
1120 if (nexthop)
1121 {
1122 if (gtw)
1123 {
1124 return gtw;
1125 }
1126 return dest->clone(dest);
1127 }
1128 return src;
1129 }
1130
1131 METHOD(kernel_net_t, get_source_addr, host_t*,
1132 private_kernel_netlink_net_t *this, host_t *dest, host_t *src)
1133 {
1134 return get_route(this, dest, FALSE, src);
1135 }
1136
1137 METHOD(kernel_net_t, get_nexthop, host_t*,
1138 private_kernel_netlink_net_t *this, host_t *dest)
1139 {
1140 return get_route(this, dest, TRUE, NULL);
1141 }
1142
1143 /**
1144 * Manages the creation and deletion of ip addresses on an interface.
1145 * By setting the appropriate nlmsg_type, the ip will be set or unset.
1146 */
1147 static status_t manage_ipaddr(private_kernel_netlink_net_t *this, int nlmsg_type,
1148 int flags, int if_index, host_t *ip)
1149 {
1150 netlink_buf_t request;
1151 struct nlmsghdr *hdr;
1152 struct ifaddrmsg *msg;
1153 chunk_t chunk;
1154
1155 memset(&request, 0, sizeof(request));
1156
1157 chunk = ip->get_address(ip);
1158
1159 hdr = (struct nlmsghdr*)request;
1160 hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
1161 hdr->nlmsg_type = nlmsg_type;
1162 hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
1163
1164 msg = (struct ifaddrmsg*)NLMSG_DATA(hdr);
1165 msg->ifa_family = ip->get_family(ip);
1166 msg->ifa_flags = 0;
1167 msg->ifa_prefixlen = 8 * chunk.len;
1168 msg->ifa_scope = RT_SCOPE_UNIVERSE;
1169 msg->ifa_index = if_index;
1170
1171 netlink_add_attribute(hdr, IFA_LOCAL, chunk, sizeof(request));
1172
1173 return this->socket->send_ack(this->socket, hdr);
1174 }
1175
1176 METHOD(kernel_net_t, add_ip, status_t,
1177 private_kernel_netlink_net_t *this, host_t *virtual_ip, host_t *iface_ip)
1178 {
1179 iface_entry_t *iface;
1180 addr_entry_t *addr;
1181 enumerator_t *addrs, *ifaces;
1182 int ifindex;
1183
1184 if (!this->install_virtual_ip)
1185 { /* disabled by config */
1186 return SUCCESS;
1187 }
1188
1189 DBG2(DBG_KNL, "adding virtual IP %H", virtual_ip);
1190
1191 this->mutex->lock(this->mutex);
1192 ifaces = this->ifaces->create_enumerator(this->ifaces);
1193 while (ifaces->enumerate(ifaces, &iface))
1194 {
1195 bool iface_found = FALSE;
1196
1197 addrs = iface->addrs->create_enumerator(iface->addrs);
1198 while (addrs->enumerate(addrs, &addr))
1199 {
1200 if (iface_ip->ip_equals(iface_ip, addr->ip))
1201 {
1202 iface_found = TRUE;
1203 }
1204 else if (virtual_ip->ip_equals(virtual_ip, addr->ip))
1205 {
1206 addr->refcount++;
1207 DBG2(DBG_KNL, "virtual IP %H already installed on %s",
1208 virtual_ip, iface->ifname);
1209 addrs->destroy(addrs);
1210 ifaces->destroy(ifaces);
1211 this->mutex->unlock(this->mutex);
1212 return SUCCESS;
1213 }
1214 }
1215 addrs->destroy(addrs);
1216
1217 if (iface_found)
1218 {
1219 ifindex = iface->ifindex;
1220 addr = malloc_thing(addr_entry_t);
1221 addr->ip = virtual_ip->clone(virtual_ip);
1222 addr->refcount = 0;
1223 addr->virtual = TRUE;
1224 addr->scope = RT_SCOPE_UNIVERSE;
1225 iface->addrs->insert_last(iface->addrs, addr);
1226
1227 if (manage_ipaddr(this, RTM_NEWADDR, NLM_F_CREATE | NLM_F_EXCL,
1228 ifindex, virtual_ip) == SUCCESS)
1229 {
1230 while (get_vip_refcount(this, virtual_ip) == 0)
1231 { /* wait until address appears */
1232 this->condvar->wait(this->condvar, this->mutex);
1233 }
1234 ifaces->destroy(ifaces);
1235 this->mutex->unlock(this->mutex);
1236 return SUCCESS;
1237 }
1238 ifaces->destroy(ifaces);
1239 this->mutex->unlock(this->mutex);
1240 DBG1(DBG_KNL, "adding virtual IP %H failed", virtual_ip);
1241 return FAILED;
1242 }
1243 }
1244 ifaces->destroy(ifaces);
1245 this->mutex->unlock(this->mutex);
1246
1247 DBG1(DBG_KNL, "interface address %H not found, unable to install"
1248 "virtual IP %H", iface_ip, virtual_ip);
1249 return FAILED;
1250 }
1251
1252 METHOD(kernel_net_t, del_ip, status_t,
1253 private_kernel_netlink_net_t *this, host_t *virtual_ip)
1254 {
1255 iface_entry_t *iface;
1256 addr_entry_t *addr;
1257 enumerator_t *addrs, *ifaces;
1258 status_t status;
1259 int ifindex;
1260
1261 if (!this->install_virtual_ip)
1262 { /* disabled by config */
1263 return SUCCESS;
1264 }
1265
1266 DBG2(DBG_KNL, "deleting virtual IP %H", virtual_ip);
1267
1268 this->mutex->lock(this->mutex);
1269 ifaces = this->ifaces->create_enumerator(this->ifaces);
1270 while (ifaces->enumerate(ifaces, &iface))
1271 {
1272 addrs = iface->addrs->create_enumerator(iface->addrs);
1273 while (addrs->enumerate(addrs, &addr))
1274 {
1275 if (virtual_ip->ip_equals(virtual_ip, addr->ip))
1276 {
1277 ifindex = iface->ifindex;
1278 if (addr->refcount == 1)
1279 {
1280 status = manage_ipaddr(this, RTM_DELADDR, 0,
1281 ifindex, virtual_ip);
1282 if (status == SUCCESS)
1283 { /* wait until the address is really gone */
1284 while (get_vip_refcount(this, virtual_ip) > 0)
1285 {
1286 this->condvar->wait(this->condvar, this->mutex);
1287 }
1288 }
1289 addrs->destroy(addrs);
1290 ifaces->destroy(ifaces);
1291 this->mutex->unlock(this->mutex);
1292 return status;
1293 }
1294 else
1295 {
1296 addr->refcount--;
1297 }
1298 DBG2(DBG_KNL, "virtual IP %H used by other SAs, not deleting",
1299 virtual_ip);
1300 addrs->destroy(addrs);
1301 ifaces->destroy(ifaces);
1302 this->mutex->unlock(this->mutex);
1303 return SUCCESS;
1304 }
1305 }
1306 addrs->destroy(addrs);
1307 }
1308 ifaces->destroy(ifaces);
1309 this->mutex->unlock(this->mutex);
1310
1311 DBG2(DBG_KNL, "virtual IP %H not cached, unable to delete", virtual_ip);
1312 return FAILED;
1313 }
1314
1315 /**
1316 * Manages source routes in the routing table.
1317 * By setting the appropriate nlmsg_type, the route gets added or removed.
1318 */
1319 static status_t manage_srcroute(private_kernel_netlink_net_t *this,
1320 int nlmsg_type, int flags, chunk_t dst_net,
1321 u_int8_t prefixlen, host_t *gateway,
1322 host_t *src_ip, char *if_name)
1323 {
1324 netlink_buf_t request;
1325 struct nlmsghdr *hdr;
1326 struct rtmsg *msg;
1327 int ifindex;
1328 chunk_t chunk;
1329
1330 /* if route is 0.0.0.0/0, we can't install it, as it would
1331 * overwrite the default route. Instead, we add two routes:
1332 * 0.0.0.0/1 and 128.0.0.0/1 */
1333 if (this->routing_table == 0 && prefixlen == 0)
1334 {
1335 chunk_t half_net;
1336 u_int8_t half_prefixlen;
1337 status_t status;
1338
1339 half_net = chunk_alloca(dst_net.len);
1340 memset(half_net.ptr, 0, half_net.len);
1341 half_prefixlen = 1;
1342
1343 status = manage_srcroute(this, nlmsg_type, flags, half_net, half_prefixlen,
1344 gateway, src_ip, if_name);
1345 half_net.ptr[0] |= 0x80;
1346 status = manage_srcroute(this, nlmsg_type, flags, half_net, half_prefixlen,
1347 gateway, src_ip, if_name);
1348 return status;
1349 }
1350
1351 memset(&request, 0, sizeof(request));
1352
1353 hdr = (struct nlmsghdr*)request;
1354 hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
1355 hdr->nlmsg_type = nlmsg_type;
1356 hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
1357
1358 msg = (struct rtmsg*)NLMSG_DATA(hdr);
1359 msg->rtm_family = src_ip->get_family(src_ip);
1360 msg->rtm_dst_len = prefixlen;
1361 msg->rtm_table = this->routing_table;
1362 msg->rtm_protocol = RTPROT_STATIC;
1363 msg->rtm_type = RTN_UNICAST;
1364 msg->rtm_scope = RT_SCOPE_UNIVERSE;
1365
1366 netlink_add_attribute(hdr, RTA_DST, dst_net, sizeof(request));
1367 chunk = src_ip->get_address(src_ip);
1368 netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request));
1369 if (gateway && gateway->get_family(gateway) == src_ip->get_family(src_ip))
1370 {
1371 chunk = gateway->get_address(gateway);
1372 netlink_add_attribute(hdr, RTA_GATEWAY, chunk, sizeof(request));
1373 }
1374 ifindex = get_interface_index(this, if_name);
1375 chunk.ptr = (char*)&ifindex;
1376 chunk.len = sizeof(ifindex);
1377 netlink_add_attribute(hdr, RTA_OIF, chunk, sizeof(request));
1378
1379 return this->socket->send_ack(this->socket, hdr);
1380 }
1381
1382 METHOD(kernel_net_t, add_route, status_t,
1383 private_kernel_netlink_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
1384 host_t *gateway, host_t *src_ip, char *if_name)
1385 {
1386 status_t status;
1387 route_entry_t *found, route = {
1388 .dst_net = dst_net,
1389 .prefixlen = prefixlen,
1390 .gateway = gateway,
1391 .src_ip = src_ip,
1392 .if_name = if_name,
1393 };
1394
1395 this->mutex->lock(this->mutex);
1396 found = this->routes->get(this->routes, &route);
1397 if (found)
1398 {
1399 this->mutex->unlock(this->mutex);
1400 return ALREADY_DONE;
1401 }
1402 found = route_entry_clone(&route);
1403 this->routes->put(this->routes, found, found);
1404 status = manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL,
1405 dst_net, prefixlen, gateway, src_ip, if_name);
1406 this->mutex->unlock(this->mutex);
1407 return status;
1408 }
1409
1410 METHOD(kernel_net_t, del_route, status_t,
1411 private_kernel_netlink_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
1412 host_t *gateway, host_t *src_ip, char *if_name)
1413 {
1414 status_t status;
1415 route_entry_t *found, route = {
1416 .dst_net = dst_net,
1417 .prefixlen = prefixlen,
1418 .gateway = gateway,
1419 .src_ip = src_ip,
1420 .if_name = if_name,
1421 };
1422
1423 this->mutex->lock(this->mutex);
1424 found = this->routes->get(this->routes, &route);
1425 if (!found)
1426 {
1427 this->mutex->unlock(this->mutex);
1428 return NOT_FOUND;
1429 }
1430 this->routes->remove(this->routes, found);
1431 route_entry_destroy(found);
1432 status = manage_srcroute(this, RTM_DELROUTE, 0, dst_net, prefixlen,
1433 gateway, src_ip, if_name);
1434 this->mutex->unlock(this->mutex);
1435 return status;
1436 }
1437
1438 /**
1439 * Initialize a list of local addresses.
1440 */
1441 static status_t init_address_list(private_kernel_netlink_net_t *this)
1442 {
1443 netlink_buf_t request;
1444 struct nlmsghdr *out, *current, *in;
1445 struct rtgenmsg *msg;
1446 size_t len;
1447 enumerator_t *ifaces, *addrs;
1448 iface_entry_t *iface;
1449 addr_entry_t *addr;
1450
1451 DBG1(DBG_KNL, "listening on interfaces:");
1452
1453 memset(&request, 0, sizeof(request));
1454
1455 in = (struct nlmsghdr*)&request;
1456 in->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
1457 in->nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT;
1458 msg = (struct rtgenmsg*)NLMSG_DATA(in);
1459 msg->rtgen_family = AF_UNSPEC;
1460
1461 /* get all links */
1462 in->nlmsg_type = RTM_GETLINK;
1463 if (this->socket->send(this->socket, in, &out, &len) != SUCCESS)
1464 {
1465 return FAILED;
1466 }
1467 current = out;
1468 while (NLMSG_OK(current, len))
1469 {
1470 switch (current->nlmsg_type)
1471 {
1472 case NLMSG_DONE:
1473 break;
1474 case RTM_NEWLINK:
1475 process_link(this, current, FALSE);
1476 /* fall through */
1477 default:
1478 current = NLMSG_NEXT(current, len);
1479 continue;
1480 }
1481 break;
1482 }
1483 free(out);
1484
1485 /* get all interface addresses */
1486 in->nlmsg_type = RTM_GETADDR;
1487 if (this->socket->send(this->socket, in, &out, &len) != SUCCESS)
1488 {
1489 return FAILED;
1490 }
1491 current = out;
1492 while (NLMSG_OK(current, len))
1493 {
1494 switch (current->nlmsg_type)
1495 {
1496 case NLMSG_DONE:
1497 break;
1498 case RTM_NEWADDR:
1499 process_addr(this, current, FALSE);
1500 /* fall through */
1501 default:
1502 current = NLMSG_NEXT(current, len);
1503 continue;
1504 }
1505 break;
1506 }
1507 free(out);
1508
1509 this->mutex->lock(this->mutex);
1510 ifaces = this->ifaces->create_enumerator(this->ifaces);
1511 while (ifaces->enumerate(ifaces, &iface))
1512 {
1513 if (iface->flags & IFF_UP)
1514 {
1515 DBG1(DBG_KNL, " %s", iface->ifname);
1516 addrs = iface->addrs->create_enumerator(iface->addrs);
1517 while (addrs->enumerate(addrs, (void**)&addr))
1518 {
1519 DBG1(DBG_KNL, " %H", addr->ip);
1520 }
1521 addrs->destroy(addrs);
1522 }
1523 }
1524 ifaces->destroy(ifaces);
1525 this->mutex->unlock(this->mutex);
1526 return SUCCESS;
1527 }
1528
1529 /**
1530 * create or delete a rule to use our routing table
1531 */
1532 static status_t manage_rule(private_kernel_netlink_net_t *this, int nlmsg_type,
1533 int family, u_int32_t table, u_int32_t prio)
1534 {
1535 netlink_buf_t request;
1536 struct nlmsghdr *hdr;
1537 struct rtmsg *msg;
1538 chunk_t chunk;
1539
1540 memset(&request, 0, sizeof(request));
1541 hdr = (struct nlmsghdr*)request;
1542 hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
1543 hdr->nlmsg_type = nlmsg_type;
1544 if (nlmsg_type == RTM_NEWRULE)
1545 {
1546 hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
1547 }
1548 hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
1549
1550 msg = (struct rtmsg*)NLMSG_DATA(hdr);
1551 msg->rtm_table = table;
1552 msg->rtm_family = family;
1553 msg->rtm_protocol = RTPROT_BOOT;
1554 msg->rtm_scope = RT_SCOPE_UNIVERSE;
1555 msg->rtm_type = RTN_UNICAST;
1556
1557 chunk = chunk_from_thing(prio);
1558 netlink_add_attribute(hdr, RTA_PRIORITY, chunk, sizeof(request));
1559
1560 return this->socket->send_ack(this->socket, hdr);
1561 }
1562
1563 METHOD(kernel_net_t, destroy, void,
1564 private_kernel_netlink_net_t *this)
1565 {
1566 enumerator_t *enumerator;
1567 route_entry_t *route;
1568
1569 if (this->routing_table)
1570 {
1571 manage_rule(this, RTM_DELRULE, AF_INET, this->routing_table,
1572 this->routing_table_prio);
1573 manage_rule(this, RTM_DELRULE, AF_INET6, this->routing_table,
1574 this->routing_table_prio);
1575 }
1576 if (this->job)
1577 {
1578 this->job->cancel(this->job);
1579 }
1580 if (this->socket_events > 0)
1581 {
1582 close(this->socket_events);
1583 }
1584 DESTROY_IF(this->socket);
1585
1586 enumerator = this->routes->create_enumerator(this->routes);
1587 while (enumerator->enumerate(enumerator, NULL, (void**)&route))
1588 {
1589 manage_srcroute(this, RTM_DELROUTE, 0, route->dst_net, route->prefixlen,
1590 route->gateway, route->src_ip, route->if_name);
1591 route_entry_destroy(route);
1592 }
1593 enumerator->destroy(enumerator);
1594 this->routes->destroy(this->routes);
1595
1596 this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
1597 this->rt_exclude->destroy(this->rt_exclude);
1598 this->condvar->destroy(this->condvar);
1599 this->mutex->destroy(this->mutex);
1600 free(this);
1601 }
1602
1603 /*
1604 * Described in header.
1605 */
1606 kernel_netlink_net_t *kernel_netlink_net_create()
1607 {
1608 private_kernel_netlink_net_t *this;
1609 struct sockaddr_nl addr;
1610 enumerator_t *enumerator;
1611 char *exclude;
1612
1613 INIT(this,
1614 .public = {
1615 .interface = {
1616 .get_interface = _get_interface_name,
1617 .create_address_enumerator = _create_address_enumerator,
1618 .get_source_addr = _get_source_addr,
1619 .get_nexthop = _get_nexthop,
1620 .add_ip = _add_ip,
1621 .del_ip = _del_ip,
1622 .add_route = _add_route,
1623 .del_route = _del_route,
1624 .destroy = _destroy,
1625 },
1626 },
1627 .socket = netlink_socket_create(NETLINK_ROUTE),
1628 .rt_exclude = linked_list_create(),
1629 .routes = hashtable_create((hashtable_hash_t)route_entry_hash,
1630 (hashtable_equals_t)route_entry_equals, 16),
1631 .ifaces = linked_list_create(),
1632 .mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
1633 .condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
1634 .routing_table = lib->settings->get_int(lib->settings,
1635 "%s.routing_table", ROUTING_TABLE, hydra->daemon),
1636 .routing_table_prio = lib->settings->get_int(lib->settings,
1637 "%s.routing_table_prio", ROUTING_TABLE_PRIO, hydra->daemon),
1638 .process_route = lib->settings->get_bool(lib->settings,
1639 "%s.process_route", TRUE, hydra->daemon),
1640 .install_virtual_ip = lib->settings->get_bool(lib->settings,
1641 "%s.install_virtual_ip", TRUE, hydra->daemon),
1642 );
1643 timerclear(&this->last_roam);
1644
1645 exclude = lib->settings->get_str(lib->settings,
1646 "%s.ignore_routing_tables", NULL, hydra->daemon);
1647 if (exclude)
1648 {
1649 char *token;
1650 uintptr_t table;
1651
1652 enumerator = enumerator_create_token(exclude, " ", " ");
1653 while (enumerator->enumerate(enumerator, &token))
1654 {
1655 errno = 0;
1656 table = strtoul(token, NULL, 10);
1657
1658 if (errno == 0)
1659 {
1660 this->rt_exclude->insert_last(this->rt_exclude, (void*)table);
1661 }
1662 }
1663 enumerator->destroy(enumerator);
1664 }
1665
1666 memset(&addr, 0, sizeof(addr));
1667 addr.nl_family = AF_NETLINK;
1668
1669 /* create and bind RT socket for events (address/interface/route changes) */
1670 this->socket_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
1671 if (this->socket_events < 0)
1672 {
1673 DBG1(DBG_KNL, "unable to create RT event socket");
1674 destroy(this);
1675 return NULL;
1676 }
1677 addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |
1678 RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE | RTMGRP_LINK;
1679 if (bind(this->socket_events, (struct sockaddr*)&addr, sizeof(addr)))
1680 {
1681 DBG1(DBG_KNL, "unable to bind RT event socket");
1682 destroy(this);
1683 return NULL;
1684 }
1685
1686 this->job = callback_job_create_with_prio((callback_job_cb_t)receive_events,
1687 this, NULL, NULL, JOB_PRIO_CRITICAL);
1688 lib->processor->queue_job(lib->processor, (job_t*)this->job);
1689
1690 if (init_address_list(this) != SUCCESS)
1691 {
1692 DBG1(DBG_KNL, "unable to get interface list");
1693 destroy(this);
1694 return NULL;
1695 }
1696
1697 if (this->routing_table)
1698 {
1699 if (manage_rule(this, RTM_NEWRULE, AF_INET, this->routing_table,
1700 this->routing_table_prio) != SUCCESS)
1701 {
1702 DBG1(DBG_KNL, "unable to create IPv4 routing table rule");
1703 }
1704 if (manage_rule(this, RTM_NEWRULE, AF_INET6, this->routing_table,
1705 this->routing_table_prio) != SUCCESS)
1706 {
1707 DBG1(DBG_KNL, "unable to create IPv6 routing table rule");
1708 }
1709 }
1710
1711 return &this->public;
1712 }