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