2 * Copyright (C) 2009-2016 Tobias Brunner
4 * Copyright (C) secunet Security Networks AG
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>.
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
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <sys/sysctl.h>
21 #include <net/if_dl.h>
23 #include <net/route.h>
27 #include "kernel_pfroute_net.h"
30 #include <utils/debug.h>
31 #include <networking/host.h>
32 #include <networking/tun_device.h>
33 #include <threading/thread.h>
34 #include <threading/mutex.h>
35 #include <threading/condvar.h>
36 #include <threading/rwlock.h>
37 #include <threading/spinlock.h>
38 #include <collections/hashtable.h>
39 #include <collections/linked_list.h>
40 #include <processing/jobs/callback_job.h>
42 #ifndef HAVE_STRUCT_SOCKADDR_SA_LEN
43 #error Cannot compile this plugin on systems where 'struct sockaddr' has no sa_len member.
46 /** properly align sockaddrs */
48 /* Apple always uses 4 bytes */
51 /* while on other platforms like FreeBSD it depends on the architecture */
52 #define SA_ALIGN sizeof(long)
54 #define SA_LEN(len) ((len) > 0 ? (((len)+SA_ALIGN-1) & ~(SA_ALIGN-1)) : SA_ALIGN)
56 /** delay before firing roam events (ms) */
57 #define ROAM_DELAY 100
59 /** delay before reinstalling routes (ms) */
60 #define ROUTE_DELAY 100
62 /** default MTU for TUN devices */
63 #define TUN_DEFAULT_MTU 1400
65 typedef struct addr_entry_t addr_entry_t
;
68 * IP address in an inface_entry_t
75 /** virtual IP managed by us */
80 * destroy a addr_entry_t object
82 static void addr_entry_destroy(addr_entry_t
*this)
84 this->ip
->destroy(this->ip
);
88 typedef struct iface_entry_t iface_entry_t
;
91 * A network interface on this system, containing addr_entry_t's
93 struct iface_entry_t
{
95 /** interface index */
98 /** name of the interface */
99 char ifname
[IFNAMSIZ
];
101 /** interface flags, as in netdevice(7) SIOCGIFFLAGS */
104 /** list of addresses as host_t */
105 linked_list_t
*addrs
;
107 /** TRUE if usable by config */
112 * destroy an interface entry
114 static void iface_entry_destroy(iface_entry_t
*this)
116 this->addrs
->destroy_function(this->addrs
, (void*)addr_entry_destroy
);
121 * check if an interface is up
123 static inline bool iface_entry_up(iface_entry_t
*iface
)
125 return (iface
->flags
& IFF_UP
) == IFF_UP
;
129 * check if an interface is up and usable
131 static inline bool iface_entry_up_and_usable(iface_entry_t
*iface
)
133 return iface
->usable
&& iface_entry_up(iface
);
136 typedef struct addr_map_entry_t addr_map_entry_t
;
139 * Entry that maps an IP address to an interface entry
141 struct addr_map_entry_t
{
142 /** The IP address */
145 /** The address entry for this IP address */
148 /** The interface this address is installed on */
149 iface_entry_t
*iface
;
153 * Hash a addr_map_entry_t object, all entries with the same IP address
154 * are stored in the same bucket
156 static u_int
addr_map_entry_hash(addr_map_entry_t
*this)
158 return chunk_hash(this->ip
->get_address(this->ip
));
162 * Compare two addr_map_entry_t objects, two entries are equal if they are
163 * installed on the same interface
165 static bool addr_map_entry_equals(addr_map_entry_t
*a
, addr_map_entry_t
*b
)
167 return a
->iface
->ifindex
== b
->iface
->ifindex
&&
168 a
->ip
->ip_equals(a
->ip
, b
->ip
);
172 * Used with get_match this finds an address entry if it is installed on
173 * an up and usable interface
175 static bool addr_map_entry_match_up_and_usable(addr_map_entry_t
*a
,
178 return !b
->addr
->virtual && iface_entry_up_and_usable(b
->iface
) &&
179 a
->ip
->ip_equals(a
->ip
, b
->ip
);
183 * Used with get_match this finds an address entry if it is installed as virtual
186 static bool addr_map_entry_match_virtual(addr_map_entry_t
*a
, addr_map_entry_t
*b
)
188 return b
->addr
->virtual && a
->ip
->ip_equals(a
->ip
, b
->ip
);
192 * Used with get_match this finds an address entry if it is installed on
193 * any active local interface
195 static bool addr_map_entry_match_up(addr_map_entry_t
*a
, addr_map_entry_t
*b
)
197 return !b
->addr
->virtual && iface_entry_up(b
->iface
) &&
198 a
->ip
->ip_equals(a
->ip
, b
->ip
);
201 typedef struct route_entry_t route_entry_t
;
204 * Installed routing entry
206 struct route_entry_t
{
207 /** Name of the interface the route is bound to */
210 /** Gateway for this route */
213 /** Destination net */
216 /** Destination net prefixlen */
221 * Clone a route_entry_t object.
223 static route_entry_t
*route_entry_clone(route_entry_t
*this)
225 route_entry_t
*route
;
228 .if_name
= strdup(this->if_name
),
229 .gateway
= this->gateway
? this->gateway
->clone(this->gateway
) : NULL
,
230 .dst_net
= chunk_clone(this->dst_net
),
231 .prefixlen
= this->prefixlen
,
237 * Destroy a route_entry_t object
239 static void route_entry_destroy(route_entry_t
*this)
242 DESTROY_IF(this->gateway
);
243 chunk_free(&this->dst_net
);
248 * Hash a route_entry_t object
250 static u_int
route_entry_hash(route_entry_t
*this)
252 return chunk_hash_inc(chunk_from_thing(this->prefixlen
),
253 chunk_hash(this->dst_net
));
257 * Compare two route_entry_t objects
259 static bool route_entry_equals(route_entry_t
*a
, route_entry_t
*b
)
261 if (a
->if_name
&& b
->if_name
&& streq(a
->if_name
, b
->if_name
) &&
262 chunk_equals(a
->dst_net
, b
->dst_net
) && a
->prefixlen
== b
->prefixlen
)
264 return (!a
->gateway
&& !b
->gateway
) || (a
->gateway
&& b
->gateway
&&
265 a
->gateway
->ip_equals(a
->gateway
, b
->gateway
));
270 typedef struct net_change_t net_change_t
;
273 * Queued network changes
275 struct net_change_t
{
276 /** Name of the interface that got activated (or an IP appeared on) */
281 * Destroy a net_change_t object
283 static void net_change_destroy(net_change_t
*this)
290 * Hash a net_change_t object
292 static u_int
net_change_hash(net_change_t
*this)
294 return chunk_hash(chunk_create(this->if_name
, strlen(this->if_name
)));
298 * Compare two net_change_t objects
300 static bool net_change_equals(net_change_t
*a
, net_change_t
*b
)
302 return streq(a
->if_name
, b
->if_name
);
305 typedef struct private_kernel_pfroute_net_t private_kernel_pfroute_net_t
;
308 * Private variables and functions of kernel_pfroute class.
310 struct private_kernel_pfroute_net_t
313 * Public part of the kernel_pfroute_t object.
315 kernel_pfroute_net_t
public;
318 * lock to access lists and maps
323 * Cached list of interfaces and their addresses (iface_entry_t)
325 linked_list_t
*ifaces
;
328 * Map for IP addresses to iface_entry_t objects (addr_map_entry_t)
333 * List of tun devices we installed for virtual IPs
338 * mutex to communicate exclusively with PF_KEY
343 * condvar to signal if PF_KEY query got a response
355 mutex_t
*routes_lock
;
358 * interface changes which may trigger route reinstallation
360 hashtable_t
*net_changes
;
363 * mutex for route reinstallation triggers
365 mutex_t
*net_changes_lock
;
368 * time of last route reinstallation
370 timeval_t last_route_reinstall
;
373 * pid to send PF_ROUTE messages with
378 * PF_ROUTE socket to communicate with the kernel
383 * sequence number for messages sent to the kernel
388 * Sequence number a query is waiting for
393 * Allocated reply message from kernel
395 struct rt_msghdr
*reply
;
398 * earliest time of the next roam event
403 * roam event due to address change
408 * lock to check and update roam event time
410 spinlock_t
*roam_lock
;
413 * Time in ms to wait for IP addresses to appear/disappear
418 * MTU to set on TUN devices
423 * whether to actually install virtual IPs
425 bool install_virtual_ip
;
430 * Forward declaration
432 static status_t
manage_route(private_kernel_pfroute_net_t
*this, int op
,
433 chunk_t dst_net
, uint8_t prefixlen
,
434 host_t
*gateway
, char *if_name
);
437 * Clear the queued network changes.
439 static void net_changes_clear(private_kernel_pfroute_net_t
*this)
441 enumerator_t
*enumerator
;
442 net_change_t
*change
;
444 enumerator
= this->net_changes
->create_enumerator(this->net_changes
);
445 while (enumerator
->enumerate(enumerator
, NULL
, (void**)&change
))
447 this->net_changes
->remove_at(this->net_changes
, enumerator
);
448 net_change_destroy(change
);
450 enumerator
->destroy(enumerator
);
454 * Act upon queued network changes.
456 static job_requeue_t
reinstall_routes(private_kernel_pfroute_net_t
*this)
458 enumerator_t
*enumerator
;
459 route_entry_t
*route
;
461 this->net_changes_lock
->lock(this->net_changes_lock
);
462 this->routes_lock
->lock(this->routes_lock
);
464 enumerator
= this->routes
->create_enumerator(this->routes
);
465 while (enumerator
->enumerate(enumerator
, NULL
, (void**)&route
))
467 net_change_t
*change
, lookup
= {
468 .if_name
= route
->if_name
,
470 /* check if a change for the outgoing interface is queued */
471 change
= this->net_changes
->get(this->net_changes
, &lookup
);
474 manage_route(this, RTM_ADD
, route
->dst_net
, route
->prefixlen
,
475 route
->gateway
, route
->if_name
);
478 enumerator
->destroy(enumerator
);
479 this->routes_lock
->unlock(this->routes_lock
);
481 net_changes_clear(this);
482 this->net_changes_lock
->unlock(this->net_changes_lock
);
483 return JOB_REQUEUE_NONE
;
487 * Queue route reinstallation caused by network changes for a given interface.
489 * The route reinstallation is delayed for a while and only done once for
490 * several calls during this delay, in order to avoid doing it too often.
491 * The interface name is freed.
493 static void queue_route_reinstall(private_kernel_pfroute_net_t
*this,
496 net_change_t
*update
, *found
;
504 this->net_changes_lock
->lock(this->net_changes_lock
);
505 found
= this->net_changes
->put(this->net_changes
, update
, update
);
508 net_change_destroy(found
);
510 time_monotonic(&now
);
511 if (timercmp(&now
, &this->last_route_reinstall
, >))
513 timeval_add_ms(&now
, ROUTE_DELAY
);
514 this->last_route_reinstall
= now
;
516 job
= (job_t
*)callback_job_create((callback_job_cb_t
)reinstall_routes
,
518 lib
->scheduler
->schedule_job_ms(lib
->scheduler
, job
, ROUTE_DELAY
);
520 this->net_changes_lock
->unlock(this->net_changes_lock
);
524 * Add an address map entry
526 static void addr_map_entry_add(private_kernel_pfroute_net_t
*this,
527 addr_entry_t
*addr
, iface_entry_t
*iface
)
529 addr_map_entry_t
*entry
;
536 entry
= this->addrs
->ht
.put(&this->addrs
->ht
, entry
, entry
);
541 * Remove an address map entry (the argument order is a bit strange because
542 * it is also used with linked_list_t.invoke_function)
544 static void addr_map_entry_remove(addr_entry_t
*addr
, iface_entry_t
*iface
,
545 private_kernel_pfroute_net_t
*this)
547 addr_map_entry_t
*entry
, lookup
= {
553 entry
= this->addrs
->ht
.remove(&this->addrs
->ht
, &lookup
);
558 * callback function that raises the delayed roam event
560 static job_requeue_t
roam_event(private_kernel_pfroute_net_t
*this)
564 this->roam_lock
->lock(this->roam_lock
);
565 address
= this->roam_address
;
566 this->roam_address
= FALSE
;
567 this->roam_lock
->unlock(this->roam_lock
);
568 charon
->kernel
->roam(charon
->kernel
, address
);
569 return JOB_REQUEUE_NONE
;
573 * fire a roaming event. we delay it for a bit and fire only one event
574 * for multiple calls. otherwise we would create too many events.
576 static void fire_roam_event(private_kernel_pfroute_net_t
*this, bool address
)
581 time_monotonic(&now
);
582 this->roam_lock
->lock(this->roam_lock
);
583 this->roam_address
|= address
;
584 if (!timercmp(&now
, &this->next_roam
, >))
586 this->roam_lock
->unlock(this->roam_lock
);
589 timeval_add_ms(&now
, ROAM_DELAY
);
590 this->next_roam
= now
;
591 this->roam_lock
->unlock(this->roam_lock
);
593 job
= (job_t
*)callback_job_create((callback_job_cb_t
)roam_event
,
595 lib
->scheduler
->schedule_job_ms(lib
->scheduler
, job
, ROAM_DELAY
);
599 * Data for enumerator over rtmsg sockaddrs
602 /** implements enumerator */
604 /** copy of attribute bitfield */
606 /** bytes remaining in buffer */
608 /** next sockaddr to enumerate */
609 struct sockaddr
*addr
;
612 METHOD(enumerator_t
, rt_enumerate
, bool,
613 rt_enumerator_t
*this, va_list args
)
615 struct sockaddr
**addr
;
618 VA_ARGS_VGET(args
, xtype
, addr
);
620 if (this->remaining
< sizeof(this->addr
->sa_len
) ||
621 this->remaining
< this->addr
->sa_len
)
625 for (i
= 0; i
< RTAX_MAX
; i
++)
628 if (this->types
& type
)
630 this->types
&= ~type
;
633 this->remaining
-= SA_LEN(this->addr
->sa_len
);
634 this->addr
= (struct sockaddr
*)((char*)this->addr
+
635 SA_LEN(this->addr
->sa_len
));
643 * Create an enumerator over sockaddrs in rt/if messages
645 static enumerator_t
*create_rt_enumerator(int types
, int remaining
,
646 struct sockaddr
*addr
)
648 rt_enumerator_t
*this;
652 .enumerate
= enumerator_enumerate_default
,
653 .venumerate
= _rt_enumerate
,
654 .destroy
= (void*)free
,
657 .remaining
= remaining
,
660 return &this->public;
664 * Create a safe enumerator over sockaddrs in rt_msghdr
666 static enumerator_t
*create_rtmsg_enumerator(struct rt_msghdr
*hdr
)
668 return create_rt_enumerator(hdr
->rtm_addrs
, hdr
->rtm_msglen
- sizeof(*hdr
),
669 (struct sockaddr
*)(hdr
+ 1));
673 * Create a safe enumerator over sockaddrs in ifa_msghdr
675 static enumerator_t
*create_ifamsg_enumerator(struct ifa_msghdr
*hdr
)
677 return create_rt_enumerator(hdr
->ifam_addrs
, hdr
->ifam_msglen
- sizeof(*hdr
),
678 (struct sockaddr
*)(hdr
+ 1));
682 * Process an RTM_*ADDR message from the kernel
684 static void process_addr(private_kernel_pfroute_net_t
*this,
685 struct ifa_msghdr
*ifa
)
687 struct sockaddr
*sockaddr
;
689 enumerator_t
*ifaces
, *addrs
;
690 iface_entry_t
*iface
;
692 bool found
= FALSE
, changed
= FALSE
, roam
= FALSE
;
693 enumerator_t
*enumerator
;
697 enumerator
= create_ifamsg_enumerator(ifa
);
698 while (enumerator
->enumerate(enumerator
, &type
, &sockaddr
))
700 if (type
== RTAX_IFA
)
702 host
= host_create_from_sockaddr(sockaddr
);
706 enumerator
->destroy(enumerator
);
708 if (!host
|| host
->is_anyaddr(host
))
714 this->lock
->write_lock(this->lock
);
715 ifaces
= this->ifaces
->create_enumerator(this->ifaces
);
716 while (ifaces
->enumerate(ifaces
, &iface
))
718 if (iface
->ifindex
== ifa
->ifam_index
)
720 addrs
= iface
->addrs
->create_enumerator(iface
->addrs
);
721 while (addrs
->enumerate(addrs
, &addr
))
723 if (host
->ip_equals(host
, addr
->ip
))
726 if (ifa
->ifam_type
== RTM_DELADDR
)
728 iface
->addrs
->remove_at(iface
->addrs
, addrs
);
729 if (!addr
->virtual && iface
->usable
)
732 DBG1(DBG_KNL
, "%H disappeared from %s",
733 host
, iface
->ifname
);
735 addr_map_entry_remove(addr
, iface
, this);
736 addr_entry_destroy(addr
);
740 addrs
->destroy(addrs
);
742 if (!found
&& ifa
->ifam_type
== RTM_NEWADDR
)
745 .ip
= host
->clone(host
),
748 ifname
= strdup(iface
->ifname
);
749 iface
->addrs
->insert_last(iface
->addrs
, addr
);
750 addr_map_entry_add(this, addr
, iface
);
753 DBG1(DBG_KNL
, "%H appeared on %s", host
, iface
->ifname
);
757 if (changed
&& iface_entry_up_and_usable(iface
))
764 ifaces
->destroy(ifaces
);
765 this->lock
->unlock(this->lock
);
770 queue_route_reinstall(this, ifname
);
779 fire_roam_event(this, TRUE
);
784 * Re-initialize address list of an interface if it changes state
786 static void repopulate_iface(private_kernel_pfroute_net_t
*this,
787 iface_entry_t
*iface
)
789 struct ifaddrs
*ifap
, *ifa
;
792 while (iface
->addrs
->remove_last(iface
->addrs
, (void**)&addr
) == SUCCESS
)
794 addr_map_entry_remove(addr
, iface
, this);
795 addr_entry_destroy(addr
);
798 if (getifaddrs(&ifap
) == 0)
800 for (ifa
= ifap
; ifa
!= NULL
; ifa
= ifa
->ifa_next
)
802 if (ifa
->ifa_addr
&& streq(ifa
->ifa_name
, iface
->ifname
))
804 switch (ifa
->ifa_addr
->sa_family
)
809 .ip
= host_create_from_sockaddr(ifa
->ifa_addr
),
811 iface
->addrs
->insert_last(iface
->addrs
, addr
);
812 addr_map_entry_add(this, addr
, iface
);
824 * Process an RTM_IFINFO message from the kernel
826 static void process_link(private_kernel_pfroute_net_t
*this,
827 struct if_msghdr
*msg
)
829 enumerator_t
*enumerator
;
830 iface_entry_t
*iface
;
831 bool roam
= FALSE
, found
= FALSE
, update_routes
= FALSE
;
833 this->lock
->write_lock(this->lock
);
834 enumerator
= this->ifaces
->create_enumerator(this->ifaces
);
835 while (enumerator
->enumerate(enumerator
, &iface
))
837 if (iface
->ifindex
== msg
->ifm_index
)
841 if (!(iface
->flags
& IFF_UP
) && (msg
->ifm_flags
& IFF_UP
))
843 roam
= update_routes
= TRUE
;
844 DBG1(DBG_KNL
, "interface %s activated", iface
->ifname
);
846 else if ((iface
->flags
& IFF_UP
) && !(msg
->ifm_flags
& IFF_UP
))
849 DBG1(DBG_KNL
, "interface %s deactivated", iface
->ifname
);
853 /* There seems to be a race condition on 10.10, where we get
854 * the RTM_IFINFO, but getifaddrs() does not return the virtual
855 * IP installed on a tun device, but we also don't get a
856 * RTM_NEWADDR. We therefore could miss the new address, letting
857 * virtual IP installation fail. Delaying getifaddrs() helps,
858 * but is obviously not a clean fix. */
861 iface
->flags
= msg
->ifm_flags
;
862 repopulate_iface(this, iface
);
867 enumerator
->destroy(enumerator
);
872 .ifindex
= msg
->ifm_index
,
873 .flags
= msg
->ifm_flags
,
874 .addrs
= linked_list_create(),
877 /* Similar to the issue described above, on 10.13 we need this delay as
878 * we might otherwise not be able to convert the index to a name yet. */
881 if (if_indextoname(iface
->ifindex
, iface
->ifname
))
883 DBG1(DBG_KNL
, "interface %s appeared", iface
->ifname
);
884 iface
->usable
= charon
->kernel
->is_interface_usable(charon
->kernel
,
886 repopulate_iface(this, iface
);
887 this->ifaces
->insert_last(this->ifaces
, iface
);
890 roam
= update_routes
= TRUE
;
898 this->lock
->unlock(this->lock
);
902 queue_route_reinstall(this, strdup(iface
->ifname
));
907 fire_roam_event(this, TRUE
);
911 #ifdef HAVE_RTM_IFANNOUNCE
914 * Process an RTM_IFANNOUNCE message from the kernel
916 static void process_announce(private_kernel_pfroute_net_t
*this,
917 struct if_announcemsghdr
*msg
)
919 enumerator_t
*enumerator
;
920 iface_entry_t
*iface
;
922 if (msg
->ifan_what
!= IFAN_DEPARTURE
)
924 /* we handle new interfaces in process_link() */
928 this->lock
->write_lock(this->lock
);
929 enumerator
= this->ifaces
->create_enumerator(this->ifaces
);
930 while (enumerator
->enumerate(enumerator
, &iface
))
932 if (iface
->ifindex
== msg
->ifan_index
)
934 DBG1(DBG_KNL
, "interface %s disappeared", iface
->ifname
);
935 this->ifaces
->remove_at(this->ifaces
, enumerator
);
936 iface_entry_destroy(iface
);
940 enumerator
->destroy(enumerator
);
941 this->lock
->unlock(this->lock
);
944 #endif /* HAVE_RTM_IFANNOUNCE */
947 * Process an RTM_*ROUTE message from the kernel
949 static void process_route(private_kernel_pfroute_net_t
*this,
950 struct rt_msghdr
*msg
)
956 * Receives PF_ROUTE messages from kernel
958 static bool receive_events(private_kernel_pfroute_net_t
*this, int fd
,
959 watcher_event_t event
)
963 struct rt_msghdr rtm
;
964 struct if_msghdr ifm
;
965 struct ifa_msghdr ifam
;
966 #ifdef HAVE_RTM_IFANNOUNCE
967 struct if_announcemsghdr ifanm
;
970 char buf
[sizeof(struct sockaddr_storage
) * RTAX_MAX
];
974 len
= recv(this->socket
, &msg
, sizeof(msg
), MSG_DONTWAIT
);
983 DBG1(DBG_KNL
, "unable to receive from PF_ROUTE event socket");
989 if (len
< offsetof(struct rt_msghdr
, rtm_flags
) || len
< msg
.rtm
.rtm_msglen
)
991 DBG1(DBG_KNL
, "received invalid PF_ROUTE message");
994 if (msg
.rtm
.rtm_version
!= RTM_VERSION
)
996 DBG1(DBG_KNL
, "received PF_ROUTE message with unsupported version: %d",
997 msg
.rtm
.rtm_version
);
1000 switch (msg
.rtm
.rtm_type
)
1004 hdrlen
= sizeof(msg
.ifam
);
1007 hdrlen
= sizeof(msg
.ifm
);
1009 #ifdef HAVE_RTM_IFANNOUNCE
1010 case RTM_IFANNOUNCE
:
1011 hdrlen
= sizeof(msg
.ifanm
);
1013 #endif /* HAVE_RTM_IFANNOUNCE */
1017 hdrlen
= sizeof(msg
.rtm
);
1022 if (msg
.rtm
.rtm_msglen
< hdrlen
)
1024 DBG1(DBG_KNL
, "ignoring short PF_ROUTE message");
1027 switch (msg
.rtm
.rtm_type
)
1031 process_addr(this, &msg
.ifam
);
1034 process_link(this, &msg
.ifm
);
1036 #ifdef HAVE_RTM_IFANNOUNCE
1037 case RTM_IFANNOUNCE
:
1038 process_announce(this, &msg
.ifanm
);
1040 #endif /* HAVE_RTM_IFANNOUNCE */
1043 process_route(this, &msg
.rtm
);
1049 this->mutex
->lock(this->mutex
);
1050 if (msg
.rtm
.rtm_pid
== this->pid
&& msg
.rtm
.rtm_seq
== this->waiting_seq
)
1052 /* seems like the message someone is waiting for, deliver */
1053 this->reply
= realloc(this->reply
, msg
.rtm
.rtm_msglen
);
1054 memcpy(this->reply
, &msg
, msg
.rtm
.rtm_msglen
);
1056 /* signal on any event, add_ip()/del_ip() might wait for it */
1057 this->condvar
->broadcast(this->condvar
);
1058 this->mutex
->unlock(this->mutex
);
1064 /** enumerator over addresses */
1066 private_kernel_pfroute_net_t
* this;
1067 /** which addresses to enumerate */
1068 kernel_address_type_t which
;
1069 } address_enumerator_t
;
1071 CALLBACK(address_enumerator_destroy
, void,
1072 address_enumerator_t
*data
)
1074 data
->this->lock
->unlock(data
->this->lock
);
1078 CALLBACK(filter_addresses
, bool,
1079 address_enumerator_t
*data
, enumerator_t
*orig
, va_list args
)
1083 struct sockaddr_in6
*sin6
;
1085 VA_ARGS_VGET(args
, out
);
1087 while (orig
->enumerate(orig
, &addr
))
1089 if (!(data
->which
& ADDR_TYPE_VIRTUAL
) && addr
->virtual)
1090 { /* skip virtual interfaces added by us */
1093 if (!(data
->which
& ADDR_TYPE_REGULAR
) && !addr
->virtual)
1094 { /* address is regular, but not requested */
1098 if (ip
->get_family(ip
) == AF_INET6
)
1100 sin6
= (struct sockaddr_in6
*)ip
->get_sockaddr(ip
);
1101 if (IN6_IS_ADDR_LINKLOCAL(&sin6
->sin6_addr
))
1102 { /* skip addresses with a unusable scope */
1113 * enumerator constructor for interfaces
1115 static enumerator_t
*create_iface_enumerator(iface_entry_t
*iface
,
1116 address_enumerator_t
*data
)
1118 return enumerator_create_filter(iface
->addrs
->create_enumerator(iface
->addrs
),
1119 filter_addresses
, data
, NULL
);
1122 CALLBACK(filter_interfaces
, bool,
1123 address_enumerator_t
*data
, enumerator_t
*orig
, va_list args
)
1125 iface_entry_t
*iface
, **out
;
1127 VA_ARGS_VGET(args
, out
);
1129 while (orig
->enumerate(orig
, &iface
))
1131 if (!(data
->which
& ADDR_TYPE_IGNORED
) && !iface
->usable
)
1132 { /* skip interfaces excluded by config */
1135 if (!(data
->which
& ADDR_TYPE_LOOPBACK
) && (iface
->flags
& IFF_LOOPBACK
))
1136 { /* ignore loopback devices */
1139 if (!(data
->which
& ADDR_TYPE_DOWN
) && !(iface
->flags
& IFF_UP
))
1140 { /* skip interfaces not up */
1149 METHOD(kernel_net_t
, create_address_enumerator
, enumerator_t
*,
1150 private_kernel_pfroute_net_t
*this, kernel_address_type_t which
)
1152 address_enumerator_t
*data
;
1159 this->lock
->read_lock(this->lock
);
1160 return enumerator_create_nested(
1161 enumerator_create_filter(
1162 this->ifaces
->create_enumerator(this->ifaces
),
1163 filter_interfaces
, data
, NULL
),
1164 (void*)create_iface_enumerator
, data
,
1165 address_enumerator_destroy
);
1168 METHOD(kernel_net_t
, get_features
, kernel_feature_t
,
1169 private_kernel_pfroute_net_t
*this)
1171 return KERNEL_REQUIRE_EXCLUDE_ROUTE
;
1174 METHOD(kernel_net_t
, get_interface_name
, bool,
1175 private_kernel_pfroute_net_t
*this, host_t
* ip
, char **name
)
1177 addr_map_entry_t
*entry
, lookup
= {
1181 if (ip
->is_anyaddr(ip
))
1185 this->lock
->read_lock(this->lock
);
1186 /* first try to find it on an up and usable interface */
1187 entry
= this->addrs
->get_match(this->addrs
, &lookup
,
1188 (void*)addr_map_entry_match_up_and_usable
);
1193 *name
= strdup(entry
->iface
->ifname
);
1194 DBG2(DBG_KNL
, "%H is on interface %s", ip
, *name
);
1196 this->lock
->unlock(this->lock
);
1199 /* check if it is a virtual IP */
1200 entry
= this->addrs
->get_match(this->addrs
, &lookup
,
1201 (void*)addr_map_entry_match_virtual
);
1206 *name
= strdup(entry
->iface
->ifname
);
1207 DBG2(DBG_KNL
, "virtual IP %H is on interface %s", ip
, *name
);
1209 this->lock
->unlock(this->lock
);
1212 /* maybe it is installed on an ignored interface */
1213 entry
= this->addrs
->get_match(this->addrs
, &lookup
,
1214 (void*)addr_map_entry_match_up
);
1216 { /* the address does not exist, is on a down interface */
1217 DBG2(DBG_KNL
, "%H is not a local address or the interface is down", ip
);
1219 this->lock
->unlock(this->lock
);
1223 METHOD(kernel_net_t
, add_ip
, status_t
,
1224 private_kernel_pfroute_net_t
*this, host_t
*vip
, int prefix
,
1227 enumerator_t
*ifaces
, *addrs
;
1228 iface_entry_t
*iface
;
1231 bool timeout
= FALSE
;
1233 if (!this->install_virtual_ip
)
1234 { /* disabled by config */
1238 tun
= tun_device_create(NULL
);
1245 prefix
= vip
->get_address(vip
).len
* 8;
1247 if (!tun
->up(tun
) || !tun
->set_address(tun
, vip
, prefix
) ||
1248 !tun
->set_mtu(tun
, this->mtu
))
1254 /* wait until address appears */
1255 this->mutex
->lock(this->mutex
);
1256 while (!timeout
&& !get_interface_name(this, vip
, NULL
))
1258 timeout
= this->condvar
->timed_wait(this->condvar
, this->mutex
,
1261 this->mutex
->unlock(this->mutex
);
1264 DBG1(DBG_KNL
, "virtual IP %H did not appear on %s",
1265 vip
, tun
->get_name(tun
));
1270 this->lock
->write_lock(this->lock
);
1271 this->tuns
->insert_last(this->tuns
, tun
);
1273 ifaces
= this->ifaces
->create_enumerator(this->ifaces
);
1274 while (ifaces
->enumerate(ifaces
, &iface
))
1276 if (streq(iface
->ifname
, tun
->get_name(tun
)))
1278 addrs
= iface
->addrs
->create_enumerator(iface
->addrs
);
1279 while (addrs
->enumerate(addrs
, &addr
))
1281 if (addr
->ip
->ip_equals(addr
->ip
, vip
))
1283 addr
->virtual = TRUE
;
1286 addrs
->destroy(addrs
);
1287 /* during IKEv1 reauthentication, children get moved from
1288 * old the new SA before the virtual IP is available. This
1289 * kills the route for our virtual IP, reinstall. */
1290 queue_route_reinstall(this, strdup(iface
->ifname
));
1294 ifaces
->destroy(ifaces
);
1295 /* lets do this while holding the lock, thus preventing another thread
1296 * from deleting the TUN device concurrently, hopefully listeners are quick
1297 * and cause no deadlocks */
1298 charon
->kernel
->tun(charon
->kernel
, tun
, TRUE
);
1299 this->lock
->unlock(this->lock
);
1304 METHOD(kernel_net_t
, del_ip
, status_t
,
1305 private_kernel_pfroute_net_t
*this, host_t
*vip
, int prefix
,
1308 enumerator_t
*enumerator
;
1311 bool timeout
= FALSE
, found
= FALSE
;
1313 if (!this->install_virtual_ip
)
1314 { /* disabled by config */
1318 this->lock
->write_lock(this->lock
);
1319 enumerator
= this->tuns
->create_enumerator(this->tuns
);
1320 while (enumerator
->enumerate(enumerator
, &tun
))
1322 addr
= tun
->get_address(tun
, NULL
);
1323 if (addr
&& addr
->ip_equals(addr
, vip
))
1325 this->tuns
->remove_at(this->tuns
, enumerator
);
1326 charon
->kernel
->tun(charon
->kernel
, tun
, FALSE
);
1332 enumerator
->destroy(enumerator
);
1333 this->lock
->unlock(this->lock
);
1339 /* wait until address disappears */
1342 this->mutex
->lock(this->mutex
);
1343 while (!timeout
&& get_interface_name(this, vip
, NULL
))
1345 timeout
= this->condvar
->timed_wait(this->condvar
, this->mutex
,
1348 this->mutex
->unlock(this->mutex
);
1351 DBG1(DBG_KNL
, "virtual IP %H did not disappear from tun", vip
);
1359 * Append a sockaddr_in/in6 of given type to routing message
1361 static void add_rt_addr(struct rt_msghdr
*hdr
, int type
, host_t
*addr
)
1367 len
= *addr
->get_sockaddr_len(addr
);
1368 memcpy((char*)hdr
+ hdr
->rtm_msglen
, addr
->get_sockaddr(addr
), len
);
1369 hdr
->rtm_msglen
+= SA_LEN(len
);
1370 hdr
->rtm_addrs
|= type
;
1375 * Append a subnet mask sockaddr using the given prefix to routing message
1377 static void add_rt_mask(struct rt_msghdr
*hdr
, int type
, int family
, int prefix
)
1381 mask
= host_create_netmask(family
, prefix
);
1384 add_rt_addr(hdr
, type
, mask
);
1385 mask
->destroy(mask
);
1390 * Append an interface name sockaddr_dl to routing message
1392 static void add_rt_ifname(struct rt_msghdr
*hdr
, int type
, char *name
)
1394 struct sockaddr_dl sdl
= {
1395 .sdl_len
= sizeof(struct sockaddr_dl
),
1396 .sdl_family
= AF_LINK
,
1397 .sdl_nlen
= strlen(name
),
1400 if (strlen(name
) <= sizeof(sdl
.sdl_data
))
1402 memcpy(sdl
.sdl_data
, name
, sdl
.sdl_nlen
);
1403 memcpy((char*)hdr
+ hdr
->rtm_msglen
, &sdl
, sdl
.sdl_len
);
1404 hdr
->rtm_msglen
+= SA_LEN(sdl
.sdl_len
);
1405 hdr
->rtm_addrs
|= type
;
1410 * Add or remove a route
1412 static status_t
manage_route(private_kernel_pfroute_net_t
*this, int op
,
1413 chunk_t dst_net
, uint8_t prefixlen
,
1414 host_t
*gateway
, char *if_name
)
1417 struct rt_msghdr hdr
;
1418 char buf
[sizeof(struct sockaddr_storage
) * RTAX_MAX
];
1421 .rtm_version
= RTM_VERSION
,
1423 .rtm_flags
= RTF_UP
| RTF_STATIC
,
1424 .rtm_pid
= this->pid
,
1425 .rtm_seq
= ref_get(&this->seq
),
1431 if (prefixlen
== 0 && dst_net
.len
)
1436 half
= chunk_clonea(dst_net
);
1437 half
.ptr
[0] |= 0x80;
1439 status
= manage_route(this, op
, half
, prefixlen
, gateway
, if_name
);
1440 if (status
!= SUCCESS
)
1446 dst
= host_create_from_chunk(AF_UNSPEC
, dst_net
, 0);
1452 if ((dst
->get_family(dst
) == AF_INET
&& prefixlen
== 32) ||
1453 (dst
->get_family(dst
) == AF_INET6
&& prefixlen
== 128))
1455 msg
.hdr
.rtm_flags
|= RTF_HOST
| RTF_GATEWAY
;
1458 msg
.hdr
.rtm_msglen
= sizeof(struct rt_msghdr
);
1459 for (type
= 0; type
< RTAX_MAX
; type
++)
1464 add_rt_addr(&msg
.hdr
, RTA_DST
, dst
);
1467 if (!(msg
.hdr
.rtm_flags
& RTF_HOST
))
1469 add_rt_mask(&msg
.hdr
, RTA_NETMASK
,
1470 dst
->get_family(dst
), prefixlen
);
1476 add_rt_ifname(&msg
.hdr
, RTA_IFP
, if_name
);
1481 gateway
->get_family(gateway
) == dst
->get_family(dst
))
1483 add_rt_addr(&msg
.hdr
, RTA_GATEWAY
, gateway
);
1492 if (send(this->socket
, &msg
, msg
.hdr
.rtm_msglen
, 0) != msg
.hdr
.rtm_msglen
)
1494 if (errno
== EEXIST
)
1496 return ALREADY_DONE
;
1498 DBG1(DBG_KNL
, "%s PF_ROUTE route failed: %s",
1499 op
== RTM_ADD
? "adding" : "deleting", strerror(errno
));
1505 METHOD(kernel_net_t
, add_route
, status_t
,
1506 private_kernel_pfroute_net_t
*this, chunk_t dst_net
, uint8_t prefixlen
,
1507 host_t
*gateway
, host_t
*src_ip
, char *if_name
, bool pass
)
1510 route_entry_t
*found
, route
= {
1512 .prefixlen
= prefixlen
,
1517 this->routes_lock
->lock(this->routes_lock
);
1518 found
= this->routes
->get(this->routes
, &route
);
1521 this->routes_lock
->unlock(this->routes_lock
);
1522 return ALREADY_DONE
;
1524 status
= manage_route(this, RTM_ADD
, dst_net
, prefixlen
, gateway
, if_name
);
1525 if (status
== SUCCESS
)
1527 found
= route_entry_clone(&route
);
1528 this->routes
->put(this->routes
, found
, found
);
1530 this->routes_lock
->unlock(this->routes_lock
);
1534 METHOD(kernel_net_t
, del_route
, status_t
,
1535 private_kernel_pfroute_net_t
*this, chunk_t dst_net
, uint8_t prefixlen
,
1536 host_t
*gateway
, host_t
*src_ip
, char *if_name
, bool pass
)
1539 route_entry_t
*found
, route
= {
1541 .prefixlen
= prefixlen
,
1546 this->routes_lock
->lock(this->routes_lock
);
1547 found
= this->routes
->get(this->routes
, &route
);
1550 this->routes_lock
->unlock(this->routes_lock
);
1553 this->routes
->remove(this->routes
, found
);
1554 route_entry_destroy(found
);
1555 status
= manage_route(this, RTM_DELETE
, dst_net
, prefixlen
, gateway
,
1557 this->routes_lock
->unlock(this->routes_lock
);
1562 * Do a route lookup for dest and return either the nexthop or the source
1565 static host_t
*get_route(private_kernel_pfroute_net_t
*this, bool nexthop
,
1566 host_t
*dest
, host_t
*src
, char **iface
)
1569 struct rt_msghdr hdr
;
1570 char buf
[sizeof(struct sockaddr_storage
) * RTAX_MAX
];
1573 .rtm_version
= RTM_VERSION
,
1574 .rtm_type
= RTM_GET
,
1575 .rtm_pid
= this->pid
,
1576 .rtm_seq
= ref_get(&this->seq
),
1579 host_t
*host
= NULL
;
1580 enumerator_t
*enumerator
;
1581 struct sockaddr
*addr
;
1582 bool failed
= FALSE
;
1586 msg
.hdr
.rtm_msglen
= sizeof(struct rt_msghdr
);
1587 for (type
= 0; type
< RTAX_MAX
; type
++)
1592 add_rt_addr(&msg
.hdr
, RTA_DST
, dest
);
1595 add_rt_addr(&msg
.hdr
, RTA_IFA
, src
);
1599 { /* add an empty IFP to ensure we get a source address */
1600 add_rt_ifname(&msg
.hdr
, RTA_IFP
, "");
1607 this->mutex
->lock(this->mutex
);
1609 while (this->waiting_seq
)
1611 this->condvar
->wait(this->condvar
, this->mutex
);
1613 this->waiting_seq
= msg
.hdr
.rtm_seq
;
1614 if (send(this->socket
, &msg
, msg
.hdr
.rtm_msglen
, 0) == msg
.hdr
.rtm_msglen
)
1618 if (this->condvar
->timed_wait(this->condvar
, this->mutex
, 1000))
1626 enumerator
= create_rtmsg_enumerator(this->reply
);
1627 while (enumerator
->enumerate(enumerator
, &type
, &addr
))
1631 if (type
== RTAX_DST
&& this->reply
->rtm_flags
& RTF_HOST
)
1632 { /* probably a cloned/cached direct route, only use that
1633 * as fallback if no gateway is found */
1634 host
= host
?: host_create_from_sockaddr(addr
);
1636 if (type
== RTAX_GATEWAY
)
1637 { /* could actually be a MAC address */
1638 host_t
*gtw
= host_create_from_sockaddr(addr
);
1645 if (type
== RTAX_IFP
&& addr
->sa_family
== AF_LINK
)
1647 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)addr
;
1651 *iface
= strndup(sdl
->sdl_data
, sdl
->sdl_nlen
);
1657 if (type
== RTAX_IFA
)
1659 host
= host_create_from_sockaddr(addr
);
1663 enumerator
->destroy(enumerator
);
1673 /* signal completion of query to a waiting thread */
1674 this->waiting_seq
= 0;
1675 this->condvar
->signal(this->condvar
);
1676 this->mutex
->unlock(this->mutex
);
1681 { /* the given source address might be gone, try again without */
1683 msg
.hdr
.rtm_seq
= ref_get(&this->seq
);
1684 msg
.hdr
.rtm_addrs
= 0;
1685 memset(msg
.buf
, 0, sizeof(msg
.buf
));
1688 DBG1(DBG_KNL
, "PF_ROUTE lookup failed: %s", strerror(errno
));
1692 host
= host
?: dest
->clone(dest
);
1695 { /* make sure the source address is not virtual and usable */
1696 addr_entry_t
*entry
, lookup
= {
1704 this->lock
->read_lock(this->lock
);
1705 entry
= this->addrs
->get_match(this->addrs
, &lookup
,
1706 (void*)addr_map_entry_match_up_and_usable
);
1707 this->lock
->unlock(this->lock
);
1710 host
->destroy(host
);
1714 DBG2(DBG_KNL
, "using %H as %s to reach %H", host
,
1715 nexthop
? "nexthop" : "address", dest
);
1719 METHOD(kernel_net_t
, get_source_addr
, host_t
*,
1720 private_kernel_pfroute_net_t
*this, host_t
*dest
, host_t
*src
)
1722 return get_route(this, FALSE
, dest
, src
, NULL
);
1725 METHOD(kernel_net_t
, get_nexthop
, host_t
*,
1726 private_kernel_pfroute_net_t
*this, host_t
*dest
, int prefix
, host_t
*src
,
1733 return get_route(this, TRUE
, dest
, src
, iface
);
1737 * Get the number of set bits in the given netmask
1739 static uint8_t sockaddr_to_netmask(sockaddr_t
*sockaddr
, host_t
*dst
)
1741 uint8_t len
= 0, i
, byte
, mask
= 0;
1742 struct sockaddr_storage ss
;
1745 /* at least some older FreeBSD versions send us shorter sockaddrs
1746 * with the family set to -1 (255) */
1747 if (sockaddr
->sa_family
== 255)
1749 memset(&ss
, 0, sizeof(ss
));
1750 memcpy(&ss
, sockaddr
, sockaddr
->sa_len
);
1751 /* use the address family and length of the destination as hint */
1752 ss
.ss_len
= *dst
->get_sockaddr_len(dst
);
1753 ss
.ss_family
= dst
->get_family(dst
);
1754 sockaddr
= (sockaddr_t
*)&ss
;
1757 switch (sockaddr
->sa_family
)
1761 addr
= (char*)&((struct sockaddr_in
*)sockaddr
)->sin_addr
;
1765 addr
= (char*)&((struct sockaddr_in6
*)sockaddr
)->sin6_addr
;
1771 for (i
= 0; i
< len
; i
++)
1795 /** enumerator over subnets */
1797 enumerator_t
public;
1798 /** sysctl result */
1800 /** length of the complete result */
1802 /** start of the current route entry */
1804 /** last subnet enumerated */
1806 /** interface of current net */
1808 } subnet_enumerator_t
;
1810 METHOD(enumerator_t
, destroy_subnet_enumerator
, void,
1811 subnet_enumerator_t
*this)
1813 DESTROY_IF(this->net
);
1819 METHOD(enumerator_t
, enumerate_subnets
, bool,
1820 subnet_enumerator_t
*this, va_list args
)
1822 enumerator_t
*enumerator
;
1824 struct rt_msghdr
*rtm
;
1825 struct sockaddr
*addr
;
1830 VA_ARGS_VGET(args
, net
, mask
, ifname
);
1834 this->current
= this->buf
;
1838 rtm
= (struct rt_msghdr
*)this->current
;
1839 this->current
+= rtm
->rtm_msglen
;
1840 DESTROY_IF(this->net
);
1843 this->ifname
= NULL
;
1846 for (; this->current
< this->buf
+ this->len
;
1847 this->current
+= rtm
->rtm_msglen
)
1849 struct sockaddr
*netmask
= NULL
;
1850 uint8_t netbits
= 0;
1852 rtm
= (struct rt_msghdr
*)this->current
;
1854 if (rtm
->rtm_version
!= RTM_VERSION
)
1858 if (rtm
->rtm_flags
& RTF_GATEWAY
||
1859 rtm
->rtm_flags
& RTF_HOST
||
1860 rtm
->rtm_flags
& RTF_REJECT
)
1864 enumerator
= create_rtmsg_enumerator(rtm
);
1865 while (enumerator
->enumerate(enumerator
, &type
, &addr
))
1867 if (type
== RTAX_DST
)
1869 this->net
= this->net
?: host_create_from_sockaddr(addr
);
1871 if (type
== RTAX_NETMASK
)
1875 if (type
== RTAX_IFP
&& addr
->sa_family
== AF_LINK
)
1877 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)addr
;
1879 this->ifname
= strndup(sdl
->sdl_data
, sdl
->sdl_nlen
);
1882 if (this->net
&& netmask
)
1884 netbits
= sockaddr_to_netmask(netmask
, this->net
);
1886 enumerator
->destroy(enumerator
);
1888 if (this->net
&& this->ifname
)
1891 *mask
= netbits
?: this->net
->get_address(this->net
).len
* 8;
1892 *ifname
= this->ifname
;
1899 METHOD(kernel_net_t
, create_local_subnet_enumerator
, enumerator_t
*,
1900 private_kernel_pfroute_net_t
*this)
1902 subnet_enumerator_t
*enumerator
;
1906 CTL_NET
, PF_ROUTE
, 0, AF_UNSPEC
, NET_RT_DUMP
, 0, 0
1909 if (sysctl(mib
, countof(mib
), NULL
, &len
, NULL
, 0) < 0)
1911 DBG2(DBG_KNL
, "enumerating local subnets failed");
1912 return enumerator_create_empty();
1915 if (sysctl(mib
, countof(mib
), buf
, &len
, NULL
, 0) < 0)
1917 DBG2(DBG_KNL
, "enumerating local subnets failed");
1919 return enumerator_create_empty();
1924 .enumerate
= enumerator_enumerate_default
,
1925 .venumerate
= _enumerate_subnets
,
1926 .destroy
= _destroy_subnet_enumerator
,
1931 return &enumerator
->public;
1935 * Initialize a list of local addresses.
1937 static status_t
init_address_list(private_kernel_pfroute_net_t
*this)
1939 struct ifaddrs
*ifap
, *ifa
;
1940 iface_entry_t
*iface
, *current
;
1942 enumerator_t
*ifaces
, *addrs
;
1944 DBG2(DBG_KNL
, "known interfaces and IP addresses:");
1946 if (getifaddrs(&ifap
) < 0)
1948 DBG1(DBG_KNL
, " failed to get interfaces!");
1952 for (ifa
= ifap
; ifa
!= NULL
; ifa
= ifa
->ifa_next
)
1954 if (ifa
->ifa_addr
== NULL
)
1958 switch(ifa
->ifa_addr
->sa_family
)
1965 ifaces
= this->ifaces
->create_enumerator(this->ifaces
);
1966 while (ifaces
->enumerate(ifaces
, ¤t
))
1968 if (streq(current
->ifname
, ifa
->ifa_name
))
1974 ifaces
->destroy(ifaces
);
1979 .ifindex
= if_nametoindex(ifa
->ifa_name
),
1980 .flags
= ifa
->ifa_flags
,
1981 .addrs
= linked_list_create(),
1982 .usable
= charon
->kernel
->is_interface_usable(
1983 charon
->kernel
, ifa
->ifa_name
),
1985 memcpy(iface
->ifname
, ifa
->ifa_name
, IFNAMSIZ
);
1986 this->ifaces
->insert_last(this->ifaces
, iface
);
1989 if (ifa
->ifa_addr
->sa_family
!= AF_LINK
)
1992 .ip
= host_create_from_sockaddr(ifa
->ifa_addr
),
1994 iface
->addrs
->insert_last(iface
->addrs
, addr
);
1995 addr_map_entry_add(this, addr
, iface
);
2002 ifaces
= this->ifaces
->create_enumerator(this->ifaces
);
2003 while (ifaces
->enumerate(ifaces
, &iface
))
2005 if (iface
->usable
&& iface
->flags
& IFF_UP
)
2007 DBG2(DBG_KNL
, " %s", iface
->ifname
);
2008 addrs
= iface
->addrs
->create_enumerator(iface
->addrs
);
2009 while (addrs
->enumerate(addrs
, (void**)&addr
))
2011 DBG2(DBG_KNL
, " %H", addr
->ip
);
2013 addrs
->destroy(addrs
);
2016 ifaces
->destroy(ifaces
);
2021 METHOD(kernel_net_t
, destroy
, void,
2022 private_kernel_pfroute_net_t
*this)
2024 enumerator_t
*enumerator
;
2025 route_entry_t
*route
;
2027 enumerator
= this->routes
->create_enumerator(this->routes
);
2028 while (enumerator
->enumerate(enumerator
, NULL
, (void**)&route
))
2030 manage_route(this, RTM_DELETE
, route
->dst_net
, route
->prefixlen
,
2031 route
->gateway
, route
->if_name
);
2032 route_entry_destroy(route
);
2034 enumerator
->destroy(enumerator
);
2035 this->routes
->destroy(this->routes
);
2036 this->routes_lock
->destroy(this->routes_lock
);
2038 if (this->socket
!= -1)
2040 lib
->watcher
->remove(lib
->watcher
, this->socket
);
2041 close(this->socket
);
2044 net_changes_clear(this);
2045 this->net_changes
->destroy(this->net_changes
);
2046 this->net_changes_lock
->destroy(this->net_changes_lock
);
2048 this->addrs
->ht
.destroy_function(&this->addrs
->ht
, (void*)free
);
2049 this->ifaces
->destroy_function(this->ifaces
, (void*)iface_entry_destroy
);
2050 this->tuns
->destroy(this->tuns
);
2051 this->lock
->destroy(this->lock
);
2052 this->mutex
->destroy(this->mutex
);
2053 this->condvar
->destroy(this->condvar
);
2054 this->roam_lock
->destroy(this->roam_lock
);
2060 * Described in header.
2062 kernel_pfroute_net_t
*kernel_pfroute_net_create()
2064 private_kernel_pfroute_net_t
*this;
2069 .get_features
= _get_features
,
2070 .get_interface
= _get_interface_name
,
2071 .create_address_enumerator
= _create_address_enumerator
,
2072 .create_local_subnet_enumerator
= _create_local_subnet_enumerator
,
2073 .get_source_addr
= _get_source_addr
,
2074 .get_nexthop
= _get_nexthop
,
2077 .add_route
= _add_route
,
2078 .del_route
= _del_route
,
2079 .destroy
= _destroy
,
2083 .ifaces
= linked_list_create(),
2084 .addrs
= hashlist_create(
2085 (hashtable_hash_t
)addr_map_entry_hash
,
2086 (hashtable_equals_t
)addr_map_entry_equals
, 16),
2087 .routes
= hashtable_create((hashtable_hash_t
)route_entry_hash
,
2088 (hashtable_equals_t
)route_entry_equals
, 16),
2089 .net_changes
= hashtable_create(
2090 (hashtable_hash_t
)net_change_hash
,
2091 (hashtable_equals_t
)net_change_equals
, 16),
2092 .tuns
= linked_list_create(),
2093 .lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
2094 .mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
2095 .condvar
= condvar_create(CONDVAR_TYPE_DEFAULT
),
2096 .routes_lock
= mutex_create(MUTEX_TYPE_DEFAULT
),
2097 .net_changes_lock
= mutex_create(MUTEX_TYPE_DEFAULT
),
2098 .roam_lock
= spinlock_create(),
2099 .vip_wait
= lib
->settings
->get_int(lib
->settings
,
2100 "%s.plugins.kernel-pfroute.vip_wait", 1000, lib
->ns
),
2101 .mtu
= lib
->settings
->get_int(lib
->settings
,
2102 "%s.plugins.kernel-pfroute.mtu", TUN_DEFAULT_MTU
, lib
->ns
),
2103 .install_virtual_ip
= lib
->settings
->get_bool(lib
->settings
,
2104 "%s.install_virtual_ip", TRUE
, lib
->ns
),
2106 timerclear(&this->last_route_reinstall
);
2107 timerclear(&this->next_roam
);
2109 /* create a PF_ROUTE socket to communicate with the kernel */
2110 this->socket
= socket(PF_ROUTE
, SOCK_RAW
, AF_UNSPEC
);
2111 if (this->socket
== -1)
2113 DBG1(DBG_KNL
, "unable to create PF_ROUTE socket");
2118 if (streq(lib
->ns
, "starter"))
2120 /* starter has no threads, so we do not register for kernel events */
2121 if (shutdown(this->socket
, SHUT_RD
) != 0)
2123 DBG1(DBG_KNL
, "closing read end of PF_ROUTE socket failed: %s",
2129 lib
->watcher
->add(lib
->watcher
, this->socket
, WATCHER_READ
,
2130 (watcher_cb_t
)receive_events
, this);
2132 if (init_address_list(this) != SUCCESS
)
2134 DBG1(DBG_KNL
, "unable to get interface list");
2139 return &this->public;