d6fd33a4455543ca24cd40e2a3d2420256da414d
[strongswan.git] / src / libhydra / plugins / kernel_pfroute / kernel_pfroute_net.c
1 /*
2 * Copyright (C) 2009-2012 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include <sys/types.h>
17 #include <sys/socket.h>
18 #include <net/if.h>
19 #include <net/if_dl.h>
20 #include <ifaddrs.h>
21 #include <net/route.h>
22 #include <unistd.h>
23 #include <errno.h>
24
25 #include "kernel_pfroute_net.h"
26
27 #include <hydra.h>
28 #include <utils/debug.h>
29 #include <networking/host.h>
30 #include <networking/tun_device.h>
31 #include <threading/thread.h>
32 #include <threading/mutex.h>
33 #include <threading/condvar.h>
34 #include <threading/rwlock.h>
35 #include <collections/hashtable.h>
36 #include <collections/linked_list.h>
37 #include <processing/jobs/callback_job.h>
38
39 #ifndef HAVE_STRUCT_SOCKADDR_SA_LEN
40 #error Cannot compile this plugin on systems where 'struct sockaddr' has no sa_len member.
41 #endif
42
43 /** delay before firing roam events (ms) */
44 #define ROAM_DELAY 100
45
46 typedef struct addr_entry_t addr_entry_t;
47
48 /**
49 * IP address in an inface_entry_t
50 */
51 struct addr_entry_t {
52
53 /** The ip address */
54 host_t *ip;
55
56 /** virtual IP managed by us */
57 bool virtual;
58 };
59
60 /**
61 * destroy a addr_entry_t object
62 */
63 static void addr_entry_destroy(addr_entry_t *this)
64 {
65 this->ip->destroy(this->ip);
66 free(this);
67 }
68
69 typedef struct iface_entry_t iface_entry_t;
70
71 /**
72 * A network interface on this system, containing addr_entry_t's
73 */
74 struct iface_entry_t {
75
76 /** interface index */
77 int ifindex;
78
79 /** name of the interface */
80 char ifname[IFNAMSIZ];
81
82 /** interface flags, as in netdevice(7) SIOCGIFFLAGS */
83 u_int flags;
84
85 /** list of addresses as host_t */
86 linked_list_t *addrs;
87
88 /** TRUE if usable by config */
89 bool usable;
90 };
91
92 /**
93 * destroy an interface entry
94 */
95 static void iface_entry_destroy(iface_entry_t *this)
96 {
97 this->addrs->destroy_function(this->addrs, (void*)addr_entry_destroy);
98 free(this);
99 }
100
101 /**
102 * check if an interface is up
103 */
104 static inline bool iface_entry_up(iface_entry_t *iface)
105 {
106 return (iface->flags & IFF_UP) == IFF_UP;
107 }
108
109 /**
110 * check if an interface is up and usable
111 */
112 static inline bool iface_entry_up_and_usable(iface_entry_t *iface)
113 {
114 return iface->usable && iface_entry_up(iface);
115 }
116
117 typedef struct addr_map_entry_t addr_map_entry_t;
118
119 /**
120 * Entry that maps an IP address to an interface entry
121 */
122 struct addr_map_entry_t {
123 /** The IP address */
124 host_t *ip;
125
126 /** The interface this address is installed on */
127 iface_entry_t *iface;
128 };
129
130 /**
131 * Hash a addr_map_entry_t object, all entries with the same IP address
132 * are stored in the same bucket
133 */
134 static u_int addr_map_entry_hash(addr_map_entry_t *this)
135 {
136 return chunk_hash(this->ip->get_address(this->ip));
137 }
138
139 /**
140 * Compare two addr_map_entry_t objects, two entries are equal if they are
141 * installed on the same interface
142 */
143 static bool addr_map_entry_equals(addr_map_entry_t *a, addr_map_entry_t *b)
144 {
145 return a->iface->ifindex == b->iface->ifindex &&
146 a->ip->ip_equals(a->ip, b->ip);
147 }
148
149 /**
150 * Used with get_match this finds an address entry if it is installed on
151 * an up and usable interface
152 */
153 static bool addr_map_entry_match_up_and_usable(addr_map_entry_t *a,
154 addr_map_entry_t *b)
155 {
156 return iface_entry_up_and_usable(b->iface) &&
157 a->ip->ip_equals(a->ip, b->ip);
158 }
159
160 /**
161 * Used with get_match this finds an address entry if it is installed on
162 * any active local interface
163 */
164 static bool addr_map_entry_match_up(addr_map_entry_t *a, addr_map_entry_t *b)
165 {
166 return iface_entry_up(b->iface) && a->ip->ip_equals(a->ip, b->ip);
167 }
168
169 typedef struct private_kernel_pfroute_net_t private_kernel_pfroute_net_t;
170
171 /**
172 * Private variables and functions of kernel_pfroute class.
173 */
174 struct private_kernel_pfroute_net_t
175 {
176 /**
177 * Public part of the kernel_pfroute_t object.
178 */
179 kernel_pfroute_net_t public;
180
181 /**
182 * lock to access lists and maps
183 */
184 rwlock_t *lock;
185
186 /**
187 * Cached list of interfaces and their addresses (iface_entry_t)
188 */
189 linked_list_t *ifaces;
190
191 /**
192 * Map for IP addresses to iface_entry_t objects (addr_map_entry_t)
193 */
194 hashtable_t *addrs;
195
196 /**
197 * List of tun devices we installed for virtual IPs
198 */
199 linked_list_t *tuns;
200
201 /**
202 * mutex to communicate exclusively with PF_KEY
203 */
204 mutex_t *mutex;
205
206 /**
207 * condvar to signal if PF_KEY query got a response
208 */
209 condvar_t *condvar;
210
211 /**
212 * pid to send PF_ROUTE messages with
213 */
214 pid_t pid;
215
216 /**
217 * PF_ROUTE socket to communicate with the kernel
218 */
219 int socket;
220
221 /**
222 * sequence number for messages sent to the kernel
223 */
224 int seq;
225
226 /**
227 * Sequence number a query is waiting for
228 */
229 int waiting_seq;
230
231 /**
232 * Allocated reply message from kernel
233 */
234 struct rt_msghdr *reply;
235
236 /**
237 * time of last roam event
238 */
239 timeval_t last_roam;
240 };
241
242 /**
243 * Add an address map entry
244 */
245 static void addr_map_entry_add(private_kernel_pfroute_net_t *this,
246 addr_entry_t *addr, iface_entry_t *iface)
247 {
248 addr_map_entry_t *entry;
249
250 if (addr->virtual)
251 { /* don't map virtual IPs */
252 return;
253 }
254
255 INIT(entry,
256 .ip = addr->ip,
257 .iface = iface,
258 );
259 entry = this->addrs->put(this->addrs, entry, entry);
260 free(entry);
261 }
262
263 /**
264 * Remove an address map entry (the argument order is a bit strange because
265 * it is also used with linked_list_t.invoke_function)
266 */
267 static void addr_map_entry_remove(addr_entry_t *addr, iface_entry_t *iface,
268 private_kernel_pfroute_net_t *this)
269 {
270 addr_map_entry_t *entry, lookup = {
271 .ip = addr->ip,
272 .iface = iface,
273 };
274
275 if (addr->virtual)
276 { /* these are never mapped, but this check avoid problems if a virtual IP
277 * equals a regular one */
278 return;
279 }
280 entry = this->addrs->remove(this->addrs, &lookup);
281 free(entry);
282 }
283
284 /**
285 * callback function that raises the delayed roam event
286 */
287 static job_requeue_t roam_event(uintptr_t address)
288 {
289 hydra->kernel_interface->roam(hydra->kernel_interface, address != 0);
290 return JOB_REQUEUE_NONE;
291 }
292
293 /**
294 * fire a roaming event. we delay it for a bit and fire only one event
295 * for multiple calls. otherwise we would create too many events.
296 */
297 static void fire_roam_event(private_kernel_pfroute_net_t *this, bool address)
298 {
299 timeval_t now;
300 job_t *job;
301
302 time_monotonic(&now);
303 if (timercmp(&now, &this->last_roam, >))
304 {
305 timeval_add_ms(&now, ROAM_DELAY);
306 this->last_roam = now;
307
308 job = (job_t*)callback_job_create((callback_job_cb_t)roam_event,
309 (void*)(uintptr_t)(address ? 1 : 0),
310 NULL, NULL);
311 lib->scheduler->schedule_job_ms(lib->scheduler, job, ROAM_DELAY);
312 }
313 }
314
315 /**
316 * Data for enumerator over rtmsg sockaddrs
317 */
318 typedef struct {
319 /** implements enumerator */
320 enumerator_t public;
321 /** copy of attribute bitfield */
322 int types;
323 /** bytes remaining in buffer */
324 int remaining;
325 /** next sockaddr to enumerate */
326 struct sockaddr *addr;
327 } rt_enumerator_t;
328
329 METHOD(enumerator_t, rt_enumerate, bool,
330 rt_enumerator_t *this, int *xtype, struct sockaddr **addr)
331 {
332 int i, type;
333
334 if (this->remaining < sizeof(this->addr->sa_len) ||
335 this->remaining < this->addr->sa_len)
336 {
337 return FALSE;
338 }
339 for (i = 0; i < RTAX_MAX; i++)
340 {
341 type = (1 << i);
342 if (this->types & type)
343 {
344 this->types &= ~type;
345 *addr = this->addr;
346 *xtype = i;
347 this->remaining -= this->addr->sa_len;
348 this->addr = (void*)this->addr + this->addr->sa_len;
349 return TRUE;
350 }
351 }
352 return FALSE;
353 }
354
355 /**
356 * Create a safe enumerator over sockaddrs in ifa/ifam/rt_msg
357 */
358 static enumerator_t *create_rtmsg_enumerator(void *hdr, size_t hdrlen)
359 {
360 struct rt_msghdr *rthdr = hdr;
361 rt_enumerator_t *this;
362
363 INIT(this,
364 .public = {
365 .enumerate = (void*)_rt_enumerate,
366 .destroy = (void*)free,
367 },
368 .types = rthdr->rtm_addrs,
369 .remaining = rthdr->rtm_msglen - hdrlen,
370 .addr = hdr + hdrlen,
371 );
372 return &this->public;
373 }
374
375 /**
376 * Process an RTM_*ADDR message from the kernel
377 */
378 static void process_addr(private_kernel_pfroute_net_t *this,
379 struct ifa_msghdr *ifa)
380 {
381 struct sockaddr *sockaddr;
382 host_t *host = NULL;
383 enumerator_t *ifaces, *addrs;
384 iface_entry_t *iface;
385 addr_entry_t *addr;
386 bool found = FALSE, changed = FALSE, roam = FALSE;
387 enumerator_t *enumerator;
388 int type;
389
390 enumerator = create_rtmsg_enumerator(ifa, sizeof(*ifa));
391 while (enumerator->enumerate(enumerator, &type, &sockaddr))
392 {
393 if (type == RTAX_IFA)
394 {
395 host = host_create_from_sockaddr(sockaddr);
396 break;
397 }
398 }
399 enumerator->destroy(enumerator);
400
401 if (!host)
402 {
403 return;
404 }
405
406 this->lock->write_lock(this->lock);
407 ifaces = this->ifaces->create_enumerator(this->ifaces);
408 while (ifaces->enumerate(ifaces, &iface))
409 {
410 if (iface->ifindex == ifa->ifam_index)
411 {
412 addrs = iface->addrs->create_enumerator(iface->addrs);
413 while (addrs->enumerate(addrs, &addr))
414 {
415 if (host->ip_equals(host, addr->ip))
416 {
417 found = TRUE;
418 if (ifa->ifam_type == RTM_DELADDR)
419 {
420 iface->addrs->remove_at(iface->addrs, addrs);
421 if (!addr->virtual && iface->usable)
422 {
423 changed = TRUE;
424 DBG1(DBG_KNL, "%H disappeared from %s",
425 host, iface->ifname);
426 }
427 addr_map_entry_remove(addr, iface, this);
428 addr_entry_destroy(addr);
429 }
430 }
431 }
432 addrs->destroy(addrs);
433
434 if (!found && ifa->ifam_type == RTM_NEWADDR)
435 {
436 INIT(addr,
437 .ip = host->clone(host),
438 );
439 changed = TRUE;
440 iface->addrs->insert_last(iface->addrs, addr);
441 addr_map_entry_add(this, addr, iface);
442 if (iface->usable)
443 {
444 DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
445 }
446 }
447
448 if (changed && iface_entry_up_and_usable(iface))
449 {
450 roam = TRUE;
451 }
452 break;
453 }
454 }
455 ifaces->destroy(ifaces);
456 this->lock->unlock(this->lock);
457 host->destroy(host);
458
459 if (roam)
460 {
461 fire_roam_event(this, TRUE);
462 }
463 }
464
465 /**
466 * Re-initialize address list of an interface if it changes state
467 */
468 static void repopulate_iface(private_kernel_pfroute_net_t *this,
469 iface_entry_t *iface)
470 {
471 struct ifaddrs *ifap, *ifa;
472 addr_entry_t *addr;
473
474 while (iface->addrs->remove_last(iface->addrs, (void**)&addr) == SUCCESS)
475 {
476 addr_map_entry_remove(addr, iface, this);
477 addr_entry_destroy(addr);
478 }
479
480 if (getifaddrs(&ifap) == 0)
481 {
482 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
483 {
484 if (ifa->ifa_addr && streq(ifa->ifa_name, iface->ifname))
485 {
486 switch (ifa->ifa_addr->sa_family)
487 {
488 case AF_INET:
489 case AF_INET6:
490 INIT(addr,
491 .ip = host_create_from_sockaddr(ifa->ifa_addr),
492 );
493 iface->addrs->insert_last(iface->addrs, addr);
494 addr_map_entry_add(this, addr, iface);
495 break;
496 default:
497 break;
498 }
499 }
500 }
501 freeifaddrs(ifap);
502 }
503 }
504
505 /**
506 * Process an RTM_IFINFO message from the kernel
507 */
508 static void process_link(private_kernel_pfroute_net_t *this,
509 struct if_msghdr *msg)
510 {
511 enumerator_t *enumerator;
512 iface_entry_t *iface;
513 bool roam = FALSE, found = FALSE;;
514
515 this->lock->write_lock(this->lock);
516 enumerator = this->ifaces->create_enumerator(this->ifaces);
517 while (enumerator->enumerate(enumerator, &iface))
518 {
519 if (iface->ifindex == msg->ifm_index)
520 {
521 if (iface->usable)
522 {
523 if (!(iface->flags & IFF_UP) && (msg->ifm_flags & IFF_UP))
524 {
525 roam = TRUE;
526 DBG1(DBG_KNL, "interface %s activated", iface->ifname);
527 }
528 else if ((iface->flags & IFF_UP) && !(msg->ifm_flags & IFF_UP))
529 {
530 roam = TRUE;
531 DBG1(DBG_KNL, "interface %s deactivated", iface->ifname);
532 }
533 }
534 iface->flags = msg->ifm_flags;
535 repopulate_iface(this, iface);
536 found = TRUE;
537 break;
538 }
539 }
540 enumerator->destroy(enumerator);
541
542 if (!found)
543 {
544 INIT(iface,
545 .ifindex = msg->ifm_index,
546 .flags = msg->ifm_flags,
547 .addrs = linked_list_create(),
548 );
549 if (if_indextoname(iface->ifindex, iface->ifname))
550 {
551 DBG1(DBG_KNL, "interface %s appeared", iface->ifname);
552 iface->usable = hydra->kernel_interface->is_interface_usable(
553 hydra->kernel_interface, iface->ifname);
554 repopulate_iface(this, iface);
555 this->ifaces->insert_last(this->ifaces, iface);
556 }
557 else
558 {
559 free(iface);
560 }
561 }
562 this->lock->unlock(this->lock);
563
564 if (roam)
565 {
566 fire_roam_event(this, TRUE);
567 }
568 }
569
570 /**
571 * Process an RTM_*ROUTE message from the kernel
572 */
573 static void process_route(private_kernel_pfroute_net_t *this,
574 struct rt_msghdr *msg)
575 {
576
577 }
578
579 /**
580 * Receives PF_ROUTE messages from kernel
581 */
582 static job_requeue_t receive_events(private_kernel_pfroute_net_t *this)
583 {
584 struct {
585 union {
586 struct rt_msghdr rtm;
587 struct if_msghdr ifm;
588 struct ifa_msghdr ifam;
589 };
590 char buf[sizeof(struct sockaddr_storage) * RTAX_MAX];
591 } msg;
592 int len, hdrlen;
593 bool oldstate;
594
595 oldstate = thread_cancelability(TRUE);
596 len = recv(this->socket, &msg, sizeof(msg), 0);
597 thread_cancelability(oldstate);
598
599 if (len < 0)
600 {
601 switch (errno)
602 {
603 case EINTR:
604 case EAGAIN:
605 return JOB_REQUEUE_DIRECT;
606 default:
607 DBG1(DBG_KNL, "unable to receive from PF_ROUTE event socket");
608 sleep(1);
609 return JOB_REQUEUE_FAIR;
610 }
611 }
612
613 if (len < offsetof(struct rt_msghdr, rtm_flags) || len < msg.rtm.rtm_msglen)
614 {
615 DBG1(DBG_KNL, "received invalid PF_ROUTE message");
616 return JOB_REQUEUE_DIRECT;
617 }
618 if (msg.rtm.rtm_version != RTM_VERSION)
619 {
620 DBG1(DBG_KNL, "received PF_ROUTE message with unsupported version: %d",
621 msg.rtm.rtm_version);
622 return JOB_REQUEUE_DIRECT;
623 }
624 switch (msg.rtm.rtm_type)
625 {
626 case RTM_NEWADDR:
627 case RTM_DELADDR:
628 hdrlen = sizeof(msg.ifam);
629 break;
630 case RTM_IFINFO:
631 hdrlen = sizeof(msg.ifm);
632 break;
633 case RTM_ADD:
634 case RTM_DELETE:
635 case RTM_GET:
636 hdrlen = sizeof(msg.rtm);
637 break;
638 default:
639 return JOB_REQUEUE_DIRECT;
640 }
641 if (msg.rtm.rtm_msglen < hdrlen)
642 {
643 DBG1(DBG_KNL, "ignoring short PF_ROUTE message");
644 return JOB_REQUEUE_DIRECT;
645 }
646 switch (msg.rtm.rtm_type)
647 {
648 case RTM_NEWADDR:
649 case RTM_DELADDR:
650 process_addr(this, &msg.ifam);
651 break;
652 case RTM_IFINFO:
653 process_link(this, &msg.ifm);
654 break;
655 case RTM_ADD:
656 case RTM_DELETE:
657 process_route(this, &msg.rtm);
658 break;
659 default:
660 break;
661 }
662
663 this->mutex->lock(this->mutex);
664 if (msg.rtm.rtm_pid == this->pid && msg.rtm.rtm_seq == this->waiting_seq)
665 {
666 /* seems like the message someone is waiting for, deliver */
667 this->reply = realloc(this->reply, msg.rtm.rtm_msglen);
668 memcpy(this->reply, &msg, msg.rtm.rtm_msglen);
669 }
670 /* signal on any event, add_ip()/del_ip() might wait for it */
671 this->condvar->broadcast(this->condvar);
672 this->mutex->unlock(this->mutex);
673
674 return JOB_REQUEUE_DIRECT;
675 }
676
677
678 /** enumerator over addresses */
679 typedef struct {
680 private_kernel_pfroute_net_t* this;
681 /** which addresses to enumerate */
682 kernel_address_type_t which;
683 } address_enumerator_t;
684
685 /**
686 * cleanup function for address enumerator
687 */
688 static void address_enumerator_destroy(address_enumerator_t *data)
689 {
690 data->this->lock->unlock(data->this->lock);
691 free(data);
692 }
693
694 /**
695 * filter for addresses
696 */
697 static bool filter_addresses(address_enumerator_t *data,
698 addr_entry_t** in, host_t** out)
699 {
700 host_t *ip;
701 if (!(data->which & ADDR_TYPE_VIRTUAL) && (*in)->virtual)
702 { /* skip virtual interfaces added by us */
703 return FALSE;
704 }
705 if (!(data->which & ADDR_TYPE_REGULAR) && !(*in)->virtual)
706 { /* address is regular, but not requested */
707 return FALSE;
708 }
709 ip = (*in)->ip;
710 if (ip->get_family(ip) == AF_INET6)
711 {
712 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ip->get_sockaddr(ip);
713 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
714 { /* skip addresses with a unusable scope */
715 return FALSE;
716 }
717 }
718 *out = ip;
719 return TRUE;
720 }
721
722 /**
723 * enumerator constructor for interfaces
724 */
725 static enumerator_t *create_iface_enumerator(iface_entry_t *iface,
726 address_enumerator_t *data)
727 {
728 return enumerator_create_filter(iface->addrs->create_enumerator(iface->addrs),
729 (void*)filter_addresses, data, NULL);
730 }
731
732 /**
733 * filter for interfaces
734 */
735 static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in,
736 iface_entry_t** out)
737 {
738 if (!(data->which & ADDR_TYPE_IGNORED) && !(*in)->usable)
739 { /* skip interfaces excluded by config */
740 return FALSE;
741 }
742 if (!(data->which & ADDR_TYPE_LOOPBACK) && ((*in)->flags & IFF_LOOPBACK))
743 { /* ignore loopback devices */
744 return FALSE;
745 }
746 if (!(data->which & ADDR_TYPE_DOWN) && !((*in)->flags & IFF_UP))
747 { /* skip interfaces not up */
748 return FALSE;
749 }
750 *out = *in;
751 return TRUE;
752 }
753
754 METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
755 private_kernel_pfroute_net_t *this, kernel_address_type_t which)
756 {
757 address_enumerator_t *data;
758
759 INIT(data,
760 .this = this,
761 .which = which,
762 );
763
764 this->lock->read_lock(this->lock);
765 return enumerator_create_nested(
766 enumerator_create_filter(
767 this->ifaces->create_enumerator(this->ifaces),
768 (void*)filter_interfaces, data, NULL),
769 (void*)create_iface_enumerator, data,
770 (void*)address_enumerator_destroy);
771 }
772
773 METHOD(kernel_net_t, get_features, kernel_feature_t,
774 private_kernel_pfroute_net_t *this)
775 {
776 return KERNEL_REQUIRE_EXCLUDE_ROUTE;
777 }
778
779 METHOD(kernel_net_t, get_interface_name, bool,
780 private_kernel_pfroute_net_t *this, host_t* ip, char **name)
781 {
782 addr_map_entry_t *entry, lookup = {
783 .ip = ip,
784 };
785
786 if (ip->is_anyaddr(ip))
787 {
788 return FALSE;
789 }
790 this->lock->read_lock(this->lock);
791 /* first try to find it on an up and usable interface */
792 entry = this->addrs->get_match(this->addrs, &lookup,
793 (void*)addr_map_entry_match_up_and_usable);
794 if (entry)
795 {
796 if (name)
797 {
798 *name = strdup(entry->iface->ifname);
799 DBG2(DBG_KNL, "%H is on interface %s", ip, *name);
800 }
801 this->lock->unlock(this->lock);
802 return TRUE;
803 }
804 /* maybe it is installed on an ignored interface */
805 entry = this->addrs->get_match(this->addrs, &lookup,
806 (void*)addr_map_entry_match_up);
807 if (!entry)
808 { /* the address does not exist, is on a down interface */
809 DBG2(DBG_KNL, "%H is not a local address or the interface is down", ip);
810 }
811 this->lock->unlock(this->lock);
812 return FALSE;
813 }
814
815 METHOD(kernel_net_t, get_source_addr, host_t*,
816 private_kernel_pfroute_net_t *this, host_t *dest, host_t *src)
817 {
818 return NULL;
819 }
820
821 METHOD(kernel_net_t, add_ip, status_t,
822 private_kernel_pfroute_net_t *this, host_t *vip, int prefix,
823 char *ifname)
824 {
825 enumerator_t *ifaces, *addrs;
826 iface_entry_t *iface;
827 addr_entry_t *addr;
828 tun_device_t *tun;
829 bool timeout = FALSE;
830
831 tun = tun_device_create(NULL);
832 if (!tun)
833 {
834 return FAILED;
835 }
836 if (prefix == -1)
837 {
838 prefix = vip->get_address(vip).len * 8;
839 }
840 if (!tun->up(tun) || !tun->set_address(tun, vip, prefix))
841 {
842 tun->destroy(tun);
843 return FAILED;
844 }
845
846 /* wait until address appears */
847 this->mutex->lock(this->mutex);
848 while (!timeout && !get_interface_name(this, vip, NULL))
849 {
850 timeout = this->condvar->timed_wait(this->condvar, this->mutex, 1000);
851 }
852 this->mutex->unlock(this->mutex);
853 if (timeout)
854 {
855 DBG1(DBG_KNL, "virtual IP %H did not appear on %s",
856 vip, tun->get_name(tun));
857 tun->destroy(tun);
858 return FAILED;
859 }
860
861 this->lock->write_lock(this->lock);
862 this->tuns->insert_last(this->tuns, tun);
863
864 ifaces = this->ifaces->create_enumerator(this->ifaces);
865 while (ifaces->enumerate(ifaces, &iface))
866 {
867 if (streq(iface->ifname, tun->get_name(tun)))
868 {
869 addrs = iface->addrs->create_enumerator(iface->addrs);
870 while (addrs->enumerate(addrs, &addr))
871 {
872 if (addr->ip->ip_equals(addr->ip, vip))
873 {
874 addr->virtual = TRUE;
875 }
876 }
877 addrs->destroy(addrs);
878 }
879 }
880 ifaces->destroy(ifaces);
881 /* lets do this while holding the lock, thus preventing another thread
882 * from deleting the TUN device concurrently, hopefully listeneres are quick
883 * and cause no deadlocks */
884 hydra->kernel_interface->tun(hydra->kernel_interface, tun, TRUE);
885 this->lock->unlock(this->lock);
886
887 return SUCCESS;
888 }
889
890 METHOD(kernel_net_t, del_ip, status_t,
891 private_kernel_pfroute_net_t *this, host_t *vip, int prefix,
892 bool wait)
893 {
894 enumerator_t *enumerator;
895 tun_device_t *tun;
896 host_t *addr;
897 bool timeout = FALSE, found = FALSE;
898
899 this->lock->write_lock(this->lock);
900 enumerator = this->tuns->create_enumerator(this->tuns);
901 while (enumerator->enumerate(enumerator, &tun))
902 {
903 addr = tun->get_address(tun, NULL);
904 if (addr && addr->ip_equals(addr, vip))
905 {
906 this->tuns->remove_at(this->tuns, enumerator);
907 hydra->kernel_interface->tun(hydra->kernel_interface, tun,
908 FALSE);
909 tun->destroy(tun);
910 found = TRUE;
911 break;
912 }
913 }
914 enumerator->destroy(enumerator);
915 this->lock->unlock(this->lock);
916
917 if (!found)
918 {
919 return NOT_FOUND;
920 }
921 /* wait until address disappears */
922 if (wait)
923 {
924 this->mutex->lock(this->mutex);
925 while (!timeout && get_interface_name(this, vip, NULL))
926 {
927 timeout = this->condvar->timed_wait(this->condvar, this->mutex, 1000);
928 }
929 this->mutex->unlock(this->mutex);
930 if (timeout)
931 {
932 DBG1(DBG_KNL, "virtual IP %H did not disappear from tun", vip);
933 return FAILED;
934 }
935 }
936 return SUCCESS;
937 }
938
939 /**
940 * Append a sockaddr_in/in6 of given type to routing message
941 */
942 static void add_rt_addr(struct rt_msghdr *hdr, int type, host_t *addr)
943 {
944 if (addr)
945 {
946 int len;
947
948 len = *addr->get_sockaddr_len(addr);
949 memcpy((char*)hdr + hdr->rtm_msglen, addr->get_sockaddr(addr), len);
950 hdr->rtm_msglen += len;
951 hdr->rtm_addrs |= type;
952 }
953 }
954
955 /**
956 * Append a subnet mask sockaddr using the given prefix to routing message
957 */
958 static void add_rt_mask(struct rt_msghdr *hdr, int type, int family, int prefix)
959 {
960 host_t *mask;
961
962 mask = host_create_netmask(family, prefix);
963 if (mask)
964 {
965 add_rt_addr(hdr, type, mask);
966 mask->destroy(mask);
967 }
968 }
969
970 /**
971 * Append an interface name sockaddr_dl to routing message
972 */
973 static void add_rt_ifname(struct rt_msghdr *hdr, int type, char *name)
974 {
975 struct sockaddr_dl sdl = {
976 .sdl_len = sizeof(struct sockaddr_dl),
977 .sdl_family = AF_LINK,
978 .sdl_nlen = strlen(name),
979 };
980
981 if (strlen(name) <= sizeof(sdl.sdl_data))
982 {
983 memcpy(sdl.sdl_data, name, sdl.sdl_nlen);
984 memcpy((char*)hdr + hdr->rtm_msglen, &sdl, sdl.sdl_len);
985 hdr->rtm_msglen += sdl.sdl_len;
986 hdr->rtm_addrs |= type;
987 }
988 }
989
990 /**
991 * Add or remove a route
992 */
993 static status_t manage_route(private_kernel_pfroute_net_t *this, int op,
994 chunk_t dst_net, u_int8_t prefixlen,
995 host_t *gateway, char *if_name)
996 {
997 struct {
998 struct rt_msghdr hdr;
999 char buf[sizeof(struct sockaddr_storage) * RTAX_MAX];
1000 } msg = {
1001 .hdr = {
1002 .rtm_version = RTM_VERSION,
1003 .rtm_type = op,
1004 .rtm_flags = RTF_UP | RTF_STATIC,
1005 .rtm_pid = this->pid,
1006 .rtm_seq = ++this->seq,
1007 },
1008 };
1009 host_t *dst;
1010 int type;
1011
1012 if (prefixlen == 0 && dst_net.len)
1013 {
1014 status_t status;
1015 chunk_t half;
1016
1017 half = chunk_clonea(dst_net);
1018 half.ptr[0] |= 0x80;
1019 prefixlen = 1;
1020 status = manage_route(this, op, half, prefixlen, gateway, if_name);
1021 if (status != SUCCESS)
1022 {
1023 return status;
1024 }
1025 }
1026
1027 dst = host_create_from_chunk(AF_UNSPEC, dst_net, 0);
1028 if (!dst)
1029 {
1030 return FAILED;
1031 }
1032
1033 if ((dst->get_family(dst) == AF_INET && prefixlen == 32) ||
1034 (dst->get_family(dst) == AF_INET6 && prefixlen == 128))
1035 {
1036 msg.hdr.rtm_flags |= RTF_HOST | RTF_GATEWAY;
1037 }
1038
1039 msg.hdr.rtm_msglen = sizeof(struct rt_msghdr);
1040 for (type = 0; type < RTAX_MAX; type++)
1041 {
1042 switch (type)
1043 {
1044 case RTAX_DST:
1045 add_rt_addr(&msg.hdr, RTA_DST, dst);
1046 break;
1047 case RTAX_NETMASK:
1048 if (!(msg.hdr.rtm_flags & RTF_HOST))
1049 {
1050 add_rt_mask(&msg.hdr, RTA_NETMASK,
1051 dst->get_family(dst), prefixlen);
1052 }
1053 break;
1054 case RTAX_GATEWAY:
1055 /* interface name seems to replace gateway on OS X */
1056 if (if_name)
1057 {
1058 add_rt_ifname(&msg.hdr, RTA_GATEWAY, if_name);
1059 }
1060 else if (gateway)
1061 {
1062 add_rt_addr(&msg.hdr, RTA_GATEWAY, gateway);
1063 }
1064 break;
1065 default:
1066 break;
1067 }
1068 }
1069 dst->destroy(dst);
1070
1071 if (send(this->socket, &msg, msg.hdr.rtm_msglen, 0) != msg.hdr.rtm_msglen)
1072 {
1073 DBG1(DBG_KNL, "%s PF_ROUTE route failed: %s",
1074 op == RTM_ADD ? "adding" : "deleting", strerror(errno));
1075 return FAILED;
1076 }
1077 return SUCCESS;
1078 }
1079
1080 METHOD(kernel_net_t, add_route, status_t,
1081 private_kernel_pfroute_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
1082 host_t *gateway, host_t *src_ip, char *if_name)
1083 {
1084 return manage_route(this, RTM_ADD, dst_net, prefixlen, gateway, if_name);
1085 }
1086
1087 METHOD(kernel_net_t, del_route, status_t,
1088 private_kernel_pfroute_net_t *this, chunk_t dst_net, u_int8_t prefixlen,
1089 host_t *gateway, host_t *src_ip, char *if_name)
1090 {
1091 return manage_route(this, RTM_DELETE, dst_net, prefixlen, gateway, if_name);
1092 }
1093
1094 METHOD(kernel_net_t, get_nexthop, host_t*,
1095 private_kernel_pfroute_net_t *this, host_t *dest, host_t *src)
1096 {
1097 struct {
1098 struct rt_msghdr hdr;
1099 char buf[sizeof(struct sockaddr_storage) * RTAX_MAX];
1100 } msg = {
1101 .hdr = {
1102 .rtm_version = RTM_VERSION,
1103 .rtm_type = RTM_GET,
1104 .rtm_pid = this->pid,
1105 .rtm_seq = ++this->seq,
1106 },
1107 };
1108 host_t *hop = NULL;
1109 enumerator_t *enumerator;
1110 struct sockaddr *addr;
1111 int type;
1112
1113 msg.hdr.rtm_msglen = sizeof(struct rt_msghdr);
1114 for (type = 0; type < RTAX_MAX; type++)
1115 {
1116 switch (type)
1117 {
1118 case RTAX_DST:
1119 add_rt_addr(&msg.hdr, RTA_DST, dest);
1120 break;
1121 case RTAX_IFA:
1122 add_rt_addr(&msg.hdr, RTA_IFA, src);
1123 break;
1124 default:
1125 break;
1126 }
1127 }
1128 this->mutex->lock(this->mutex);
1129
1130 while (this->waiting_seq)
1131 {
1132 this->condvar->wait(this->condvar, this->mutex);
1133 }
1134 this->waiting_seq = msg.hdr.rtm_seq;
1135 if (send(this->socket, &msg, msg.hdr.rtm_msglen, 0) == msg.hdr.rtm_msglen)
1136 {
1137 while (TRUE)
1138 {
1139 if (this->condvar->timed_wait(this->condvar, this->mutex, 1000))
1140 { /* timed out? */
1141 break;
1142 }
1143 if (this->reply->rtm_msglen < sizeof(*this->reply) ||
1144 msg.hdr.rtm_seq != this->reply->rtm_seq)
1145 {
1146 continue;
1147 }
1148 enumerator = create_rtmsg_enumerator(this->reply,
1149 sizeof(*this->reply));
1150 while (enumerator->enumerate(enumerator, &type, &addr))
1151 {
1152 if (type == RTAX_GATEWAY)
1153 {
1154 hop = host_create_from_sockaddr(addr);
1155 break;
1156 }
1157 }
1158 enumerator->destroy(enumerator);
1159 break;
1160 }
1161 }
1162 else
1163 {
1164 DBG1(DBG_KNL, "PF_ROUTE lookup failed: %s", strerror(errno));
1165 }
1166 /* signal completion of query to a waiting thread */
1167 this->waiting_seq = 0;
1168 this->condvar->signal(this->condvar);
1169 this->mutex->unlock(this->mutex);
1170
1171 return hop;
1172 }
1173
1174 /**
1175 * Initialize a list of local addresses.
1176 */
1177 static status_t init_address_list(private_kernel_pfroute_net_t *this)
1178 {
1179 struct ifaddrs *ifap, *ifa;
1180 iface_entry_t *iface, *current;
1181 addr_entry_t *addr;
1182 enumerator_t *ifaces, *addrs;
1183
1184 DBG2(DBG_KNL, "known interfaces and IP addresses:");
1185
1186 if (getifaddrs(&ifap) < 0)
1187 {
1188 DBG1(DBG_KNL, " failed to get interfaces!");
1189 return FAILED;
1190 }
1191
1192 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
1193 {
1194 if (ifa->ifa_addr == NULL)
1195 {
1196 continue;
1197 }
1198 switch(ifa->ifa_addr->sa_family)
1199 {
1200 case AF_LINK:
1201 case AF_INET:
1202 case AF_INET6:
1203 {
1204 iface = NULL;
1205 ifaces = this->ifaces->create_enumerator(this->ifaces);
1206 while (ifaces->enumerate(ifaces, &current))
1207 {
1208 if (streq(current->ifname, ifa->ifa_name))
1209 {
1210 iface = current;
1211 break;
1212 }
1213 }
1214 ifaces->destroy(ifaces);
1215
1216 if (!iface)
1217 {
1218 INIT(iface,
1219 .ifindex = if_nametoindex(ifa->ifa_name),
1220 .flags = ifa->ifa_flags,
1221 .addrs = linked_list_create(),
1222 .usable = hydra->kernel_interface->is_interface_usable(
1223 hydra->kernel_interface, ifa->ifa_name),
1224 );
1225 memcpy(iface->ifname, ifa->ifa_name, IFNAMSIZ);
1226 this->ifaces->insert_last(this->ifaces, iface);
1227 }
1228
1229 if (ifa->ifa_addr->sa_family != AF_LINK)
1230 {
1231 INIT(addr,
1232 .ip = host_create_from_sockaddr(ifa->ifa_addr),
1233 );
1234 iface->addrs->insert_last(iface->addrs, addr);
1235 addr_map_entry_add(this, addr, iface);
1236 }
1237 }
1238 }
1239 }
1240 freeifaddrs(ifap);
1241
1242 ifaces = this->ifaces->create_enumerator(this->ifaces);
1243 while (ifaces->enumerate(ifaces, &iface))
1244 {
1245 if (iface->usable && iface->flags & IFF_UP)
1246 {
1247 DBG2(DBG_KNL, " %s", iface->ifname);
1248 addrs = iface->addrs->create_enumerator(iface->addrs);
1249 while (addrs->enumerate(addrs, (void**)&addr))
1250 {
1251 DBG2(DBG_KNL, " %H", addr->ip);
1252 }
1253 addrs->destroy(addrs);
1254 }
1255 }
1256 ifaces->destroy(ifaces);
1257
1258 return SUCCESS;
1259 }
1260
1261 METHOD(kernel_net_t, destroy, void,
1262 private_kernel_pfroute_net_t *this)
1263 {
1264 enumerator_t *enumerator;
1265 addr_entry_t *addr;
1266
1267 if (this->socket != -1)
1268 {
1269 close(this->socket);
1270 }
1271 enumerator = this->addrs->create_enumerator(this->addrs);
1272 while (enumerator->enumerate(enumerator, NULL, (void**)&addr))
1273 {
1274 free(addr);
1275 }
1276 enumerator->destroy(enumerator);
1277 this->addrs->destroy(this->addrs);
1278 this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
1279 this->tuns->destroy(this->tuns);
1280 this->lock->destroy(this->lock);
1281 this->mutex->destroy(this->mutex);
1282 this->condvar->destroy(this->condvar);
1283 free(this->reply);
1284 free(this);
1285 }
1286
1287 /*
1288 * Described in header.
1289 */
1290 kernel_pfroute_net_t *kernel_pfroute_net_create()
1291 {
1292 private_kernel_pfroute_net_t *this;
1293
1294 INIT(this,
1295 .public = {
1296 .interface = {
1297 .get_features = _get_features,
1298 .get_interface = _get_interface_name,
1299 .create_address_enumerator = _create_address_enumerator,
1300 .get_source_addr = _get_source_addr,
1301 .get_nexthop = _get_nexthop,
1302 .add_ip = _add_ip,
1303 .del_ip = _del_ip,
1304 .add_route = _add_route,
1305 .del_route = _del_route,
1306 .destroy = _destroy,
1307 },
1308 },
1309 .pid = getpid(),
1310 .ifaces = linked_list_create(),
1311 .addrs = hashtable_create(
1312 (hashtable_hash_t)addr_map_entry_hash,
1313 (hashtable_equals_t)addr_map_entry_equals, 16),
1314 .tuns = linked_list_create(),
1315 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
1316 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
1317 .condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
1318 );
1319
1320 /* create a PF_ROUTE socket to communicate with the kernel */
1321 this->socket = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
1322 if (this->socket == -1)
1323 {
1324 DBG1(DBG_KNL, "unable to create PF_ROUTE socket");
1325 destroy(this);
1326 return NULL;
1327 }
1328
1329 if (streq(hydra->daemon, "starter"))
1330 {
1331 /* starter has no threads, so we do not register for kernel events */
1332 if (shutdown(this->socket, SHUT_RD) != 0)
1333 {
1334 DBG1(DBG_KNL, "closing read end of PF_ROUTE socket failed: %s",
1335 strerror(errno));
1336 }
1337 }
1338 else
1339 {
1340 lib->processor->queue_job(lib->processor,
1341 (job_t*)callback_job_create_with_prio(
1342 (callback_job_cb_t)receive_events, this, NULL,
1343 (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
1344 }
1345 if (init_address_list(this) != SUCCESS)
1346 {
1347 DBG1(DBG_KNL, "unable to get interface list");
1348 destroy(this);
1349 return NULL;
1350 }
1351
1352 return &this->public;
1353 }