aboutsummaryrefslogtreecommitdiffstats
path: root/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2013-08-12 11:23:34 +0200
committerTobias Brunner <tobias@strongswan.org>2013-08-12 12:02:55 +0200
commit77d4a0281afc3e84a58589e2b10e81d2a39ebcff (patch)
tree09e5d1a88194eb4b76abdbca01bd8e8a3d65258d /src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
parenta24515c515de7c51159c07be0e9b873eaa8ec8d5 (diff)
downloadstrongswan-77d4a0281afc3e84a58589e2b10e81d2a39ebcff.tar.bz2
strongswan-77d4a0281afc3e84a58589e2b10e81d2a39ebcff.tar.xz
kernel-netlink: Ensure address changes are not missed in roam events
If multiple roam events are triggered within ROAM_DELAY, only one job is created. The old code set the address flag to the value of the last triggering call. So if a route change followed an address change within ROAM_DELAY the address change was missed by the upper layers, e.g. causing it not to update the list of addresses via MOBIKE. The new code now keeps the state of the address flag until the job is actually executed, which still has some issues. For instance, if an address disappears and reappears within ROAM_RELAY, the flag would not have to be set to TRUE. So address updates might occasionally get triggered where none would actually be required. Fixes #374.
Diffstat (limited to 'src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c')
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
index e129ab131..89fb076ad 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
@@ -394,6 +394,11 @@ struct private_kernel_netlink_net_t {
timeval_t next_roam;
/**
+ * roam event due to address change
+ */
+ bool roam_address;
+
+ /**
* lock to check and update roam event time
*/
spinlock_t *roam_lock;
@@ -696,9 +701,15 @@ static host_t *get_interface_address(private_kernel_netlink_net_t *this,
/**
* callback function that raises the delayed roam event
*/
-static job_requeue_t roam_event(uintptr_t address)
+static job_requeue_t roam_event(private_kernel_netlink_net_t *this)
{
- hydra->kernel_interface->roam(hydra->kernel_interface, address != 0);
+ bool address;
+
+ this->roam_lock->lock(this->roam_lock);
+ address = this->roam_address;
+ this->roam_address = FALSE;
+ this->roam_lock->unlock(this->roam_lock);
+ hydra->kernel_interface->roam(hydra->kernel_interface, address);
return JOB_REQUEUE_NONE;
}
@@ -725,11 +736,11 @@ static void fire_roam_event(private_kernel_netlink_net_t *this, bool address)
}
timeval_add_ms(&now, ROAM_DELAY);
this->next_roam = now;
+ this->roam_address |= address;
this->roam_lock->unlock(this->roam_lock);
job = (job_t*)callback_job_create((callback_job_cb_t)roam_event,
- (void*)(uintptr_t)(address ? 1 : 0),
- NULL, NULL);
+ this, NULL, NULL);
lib->scheduler->schedule_job_ms(lib->scheduler, job, ROAM_DELAY);
}