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