further MOBIKE stuff:
kernel properly reports network reconfiguration and informs all IKE_SAs MOBIKE in IKE_AUTH: MOBIKE_SUPPORTED notify and address exchange reestablishment of IKE_SAs on network reconfiguration kinda works not stable yet!
This commit is contained in:
@@ -59,6 +59,7 @@ processing/jobs/rekey_ike_sa_job.c processing/jobs/rekey_ike_sa_job.h \
|
|||||||
processing/jobs/retransmit_job.c processing/jobs/retransmit_job.h \
|
processing/jobs/retransmit_job.c processing/jobs/retransmit_job.h \
|
||||||
processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \
|
processing/jobs/send_dpd_job.c processing/jobs/send_dpd_job.h \
|
||||||
processing/jobs/send_keepalive_job.c processing/jobs/send_keepalive_job.h \
|
processing/jobs/send_keepalive_job.c processing/jobs/send_keepalive_job.h \
|
||||||
|
processing/jobs/roam_job.c processing/jobs/roam_job.h \
|
||||||
processing/scheduler.c processing/scheduler.h \
|
processing/scheduler.c processing/scheduler.h \
|
||||||
processing/processor.c processing/processor.h \
|
processing/processor.c processing/processor.h \
|
||||||
sa/authenticators/authenticator.c sa/authenticators/authenticator.h \
|
sa/authenticators/authenticator.c sa/authenticators/authenticator.h \
|
||||||
@@ -81,6 +82,7 @@ sa/tasks/ike_delete.c sa/tasks/ike_delete.h \
|
|||||||
sa/tasks/ike_dpd.c sa/tasks/ike_dpd.h \
|
sa/tasks/ike_dpd.c sa/tasks/ike_dpd.h \
|
||||||
sa/tasks/ike_init.c sa/tasks/ike_init.h \
|
sa/tasks/ike_init.c sa/tasks/ike_init.h \
|
||||||
sa/tasks/ike_natd.c sa/tasks/ike_natd.h \
|
sa/tasks/ike_natd.c sa/tasks/ike_natd.h \
|
||||||
|
sa/tasks/ike_mobike.c sa/tasks/ike_mobike.h \
|
||||||
sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \
|
sa/tasks/ike_rekey.c sa/tasks/ike_rekey.h \
|
||||||
sa/tasks/ike_reauth.c sa/tasks/ike_reauth.h \
|
sa/tasks/ike_reauth.c sa/tasks/ike_reauth.h \
|
||||||
sa/tasks/task.c sa/tasks/task.h
|
sa/tasks/task.c sa/tasks/task.h
|
||||||
|
|||||||
@@ -189,6 +189,8 @@ encoding_rule_t notify_payload_encodings[] = {
|
|||||||
*/
|
*/
|
||||||
static status_t verify(private_notify_payload_t *this)
|
static status_t verify(private_notify_payload_t *this)
|
||||||
{
|
{
|
||||||
|
bool bad_length = FALSE;
|
||||||
|
|
||||||
switch (this->protocol_id)
|
switch (this->protocol_id)
|
||||||
{
|
{
|
||||||
case PROTO_NONE:
|
case PROTO_NONE:
|
||||||
@@ -205,30 +207,9 @@ static status_t verify(private_notify_payload_t *this)
|
|||||||
{
|
{
|
||||||
case INVALID_KE_PAYLOAD:
|
case INVALID_KE_PAYLOAD:
|
||||||
{
|
{
|
||||||
/* check notification data */
|
|
||||||
diffie_hellman_group_t dh_group;
|
|
||||||
if (this->notification_data.len != 2)
|
if (this->notification_data.len != 2)
|
||||||
{
|
{
|
||||||
DBG1(DBG_ENC, "invalid notify data length for %N (%d)",
|
bad_length = TRUE;
|
||||||
notify_type_names, this->notify_type,
|
|
||||||
this->notification_data.len);
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
dh_group = ntohs(*((u_int16_t*)this->notification_data.ptr));
|
|
||||||
switch (dh_group)
|
|
||||||
{
|
|
||||||
case MODP_768_BIT:
|
|
||||||
case MODP_1024_BIT:
|
|
||||||
case MODP_1536_BIT:
|
|
||||||
case MODP_2048_BIT:
|
|
||||||
case MODP_3072_BIT:
|
|
||||||
case MODP_4096_BIT:
|
|
||||||
case MODP_6144_BIT:
|
|
||||||
case MODP_8192_BIT:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DBG1(DBG_ENC, "Bad DH group (%d)", dh_group);
|
|
||||||
return FAILED;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -237,9 +218,7 @@ static status_t verify(private_notify_payload_t *this)
|
|||||||
{
|
{
|
||||||
if (this->notification_data.len != HASH_SIZE_SHA1)
|
if (this->notification_data.len != HASH_SIZE_SHA1)
|
||||||
{
|
{
|
||||||
DBG1(DBG_ENC, "invalid %N notify length",
|
bad_length = TRUE;
|
||||||
notify_type_names, this->notify_type);
|
|
||||||
return FAILED;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -249,9 +228,23 @@ static status_t verify(private_notify_payload_t *this)
|
|||||||
{
|
{
|
||||||
if (this->notification_data.len != 0)
|
if (this->notification_data.len != 0)
|
||||||
{
|
{
|
||||||
DBG1(DBG_ENC, "invalid %N notify",
|
bad_length = TRUE;
|
||||||
notify_type_names, this->notify_type);
|
}
|
||||||
return FAILED;
|
break;
|
||||||
|
}
|
||||||
|
case ADDITIONAL_IP4_ADDRESS:
|
||||||
|
{
|
||||||
|
if (this->notification_data.len != 4)
|
||||||
|
{
|
||||||
|
bad_length = TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ADDITIONAL_IP6_ADDRESS:
|
||||||
|
{
|
||||||
|
if (this->notification_data.len != 16)
|
||||||
|
{
|
||||||
|
bad_length = TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -259,6 +252,13 @@ static status_t verify(private_notify_payload_t *this)
|
|||||||
/* TODO: verify */
|
/* TODO: verify */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (bad_length)
|
||||||
|
{
|
||||||
|
DBG1(DBG_ENC, "invalid notify data length for %N (%d)",
|
||||||
|
notify_type_names, this->notify_type,
|
||||||
|
this->notification_data.len);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
#include <processing/jobs/rekey_child_sa_job.h>
|
#include <processing/jobs/rekey_child_sa_job.h>
|
||||||
#include <processing/jobs/acquire_job.h>
|
#include <processing/jobs/acquire_job.h>
|
||||||
#include <processing/jobs/callback_job.h>
|
#include <processing/jobs/callback_job.h>
|
||||||
|
#include <processing/jobs/roam_job.h>
|
||||||
|
|
||||||
/** kernel level protocol identifiers */
|
/** kernel level protocol identifiers */
|
||||||
#define KERNEL_ESP 50
|
#define KERNEL_ESP 50
|
||||||
@@ -217,37 +218,35 @@ struct policy_entry_t {
|
|||||||
u_int refcount;
|
u_int refcount;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct vip_entry_t vip_entry_t;
|
typedef struct addr_entry_t addr_entry_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Installed virtual ip
|
* IP address in an inface_entry_t
|
||||||
*/
|
*/
|
||||||
struct vip_entry_t {
|
struct addr_entry_t {
|
||||||
/** Index of the interface the ip is bound to */
|
|
||||||
u_int8_t if_index;
|
|
||||||
|
|
||||||
/** The ip address */
|
/** The ip address */
|
||||||
host_t *ip;
|
host_t *ip;
|
||||||
|
|
||||||
/** Number of times this IP is used */
|
/** Number of times this IP is used, if virtual */
|
||||||
u_int refcount;
|
u_int refcount;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* destroy a vip_entry_t object
|
* destroy a addr_entry_t object
|
||||||
*/
|
*/
|
||||||
static void vip_entry_destroy(vip_entry_t *this)
|
static void addr_entry_destroy(addr_entry_t *this)
|
||||||
{
|
{
|
||||||
this->ip->destroy(this->ip);
|
this->ip->destroy(this->ip);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct interface_entry_t interface_entry_t;
|
typedef struct iface_entry_t iface_entry_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A network interface on this system, containing addresses
|
* A network interface on this system, containing addr_entry_t's
|
||||||
*/
|
*/
|
||||||
struct interface_entry_t {
|
struct iface_entry_t {
|
||||||
|
|
||||||
/** interface index */
|
/** interface index */
|
||||||
int ifindex;
|
int ifindex;
|
||||||
@@ -259,15 +258,15 @@ struct interface_entry_t {
|
|||||||
u_int flags;
|
u_int flags;
|
||||||
|
|
||||||
/** list of addresses as host_t */
|
/** list of addresses as host_t */
|
||||||
linked_list_t *addresses;
|
linked_list_t *addrs;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* destroy an interface entry
|
* destroy an interface entry
|
||||||
*/
|
*/
|
||||||
static void interface_entry_destroy(interface_entry_t *this)
|
static void iface_entry_destroy(iface_entry_t *this)
|
||||||
{
|
{
|
||||||
this->addresses->destroy_offset(this->addresses, offsetof(host_t, destroy));
|
this->addrs->destroy_function(this->addrs, (void*)addr_entry_destroy);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,19 +287,14 @@ struct private_kernel_interface_t {
|
|||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of installed policies (kernel_entry_t)
|
* List of installed policies (policy_entry_t)
|
||||||
*/
|
*/
|
||||||
linked_list_t *policies;
|
linked_list_t *policies;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of installed virtual IPs. (vip_entry_t)
|
* Cached list of interfaces and its adresses (iface_entry_t)
|
||||||
*/
|
*/
|
||||||
linked_list_t *vips;
|
linked_list_t *ifaces;
|
||||||
|
|
||||||
/**
|
|
||||||
* Cached list of interfaces and its adresses (interface_entry_t)
|
|
||||||
*/
|
|
||||||
linked_list_t *interfaces;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iterator used in hook()
|
* iterator used in hook()
|
||||||
@@ -529,8 +523,9 @@ static void process_link(private_kernel_interface_t *this,
|
|||||||
struct rtattr *rta = IFLA_RTA(msg);
|
struct rtattr *rta = IFLA_RTA(msg);
|
||||||
size_t rtasize = IFLA_PAYLOAD (hdr);
|
size_t rtasize = IFLA_PAYLOAD (hdr);
|
||||||
iterator_t *iterator;
|
iterator_t *iterator;
|
||||||
interface_entry_t *current, *entry = NULL;
|
iface_entry_t *current, *entry = NULL;
|
||||||
char *name = NULL;
|
char *name = NULL;
|
||||||
|
bool update = FALSE;
|
||||||
|
|
||||||
while(RTA_OK(rta, rtasize))
|
while(RTA_OK(rta, rtasize))
|
||||||
{
|
{
|
||||||
@@ -555,8 +550,8 @@ static void process_link(private_kernel_interface_t *this,
|
|||||||
{ /* ignore loopback interfaces */
|
{ /* ignore loopback interfaces */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
iterator = this->interfaces->create_iterator_locked(this->interfaces,
|
iterator = this->ifaces->create_iterator_locked(this->ifaces,
|
||||||
&this->mutex);
|
&this->mutex);
|
||||||
while (iterator->iterate(iterator, (void**)¤t))
|
while (iterator->iterate(iterator, (void**)¤t))
|
||||||
{
|
{
|
||||||
if (current->ifindex == msg->ifi_index)
|
if (current->ifindex == msg->ifi_index)
|
||||||
@@ -567,11 +562,11 @@ static void process_link(private_kernel_interface_t *this,
|
|||||||
}
|
}
|
||||||
if (!entry)
|
if (!entry)
|
||||||
{
|
{
|
||||||
entry = malloc_thing(interface_entry_t);
|
entry = malloc_thing(iface_entry_t);
|
||||||
entry->ifindex = msg->ifi_index;
|
entry->ifindex = msg->ifi_index;
|
||||||
entry->flags = 0;
|
entry->flags = 0;
|
||||||
entry->addresses = linked_list_create();
|
entry->addrs = linked_list_create();
|
||||||
this->interfaces->insert_last(this->interfaces, entry);
|
this->ifaces->insert_last(this->ifaces, entry);
|
||||||
}
|
}
|
||||||
memcpy(entry->ifname, name, IFNAMSIZ);
|
memcpy(entry->ifname, name, IFNAMSIZ);
|
||||||
entry->ifname[IFNAMSIZ-1] = '\0';
|
entry->ifname[IFNAMSIZ-1] = '\0';
|
||||||
@@ -579,10 +574,12 @@ static void process_link(private_kernel_interface_t *this,
|
|||||||
{
|
{
|
||||||
if (!(entry->flags & IFF_UP) && (msg->ifi_flags & IFF_UP))
|
if (!(entry->flags & IFF_UP) && (msg->ifi_flags & IFF_UP))
|
||||||
{
|
{
|
||||||
|
update = TRUE;
|
||||||
DBG1(DBG_KNL, "interface %s activated", name);
|
DBG1(DBG_KNL, "interface %s activated", name);
|
||||||
}
|
}
|
||||||
if ((entry->flags & IFF_UP) && !(msg->ifi_flags & IFF_UP))
|
if ((entry->flags & IFF_UP) && !(msg->ifi_flags & IFF_UP))
|
||||||
{
|
{
|
||||||
|
update = TRUE;
|
||||||
DBG1(DBG_KNL, "interface %s deactivated", name);
|
DBG1(DBG_KNL, "interface %s deactivated", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -592,8 +589,8 @@ static void process_link(private_kernel_interface_t *this,
|
|||||||
}
|
}
|
||||||
case RTM_DELLINK:
|
case RTM_DELLINK:
|
||||||
{
|
{
|
||||||
iterator = this->interfaces->create_iterator_locked(this->interfaces,
|
iterator = this->ifaces->create_iterator_locked(this->ifaces,
|
||||||
&this->mutex);
|
&this->mutex);
|
||||||
while (iterator->iterate(iterator, (void**)¤t))
|
while (iterator->iterate(iterator, (void**)¤t))
|
||||||
{
|
{
|
||||||
if (current->ifindex == msg->ifi_index)
|
if (current->ifindex == msg->ifi_index)
|
||||||
@@ -608,6 +605,12 @@ static void process_link(private_kernel_interface_t *this,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* send an update to all IKE_SAs */
|
||||||
|
if (update && event)
|
||||||
|
{
|
||||||
|
charon->processor->queue_job(charon->processor, (job_t*)roam_job_create());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -620,9 +623,11 @@ static void process_addr(private_kernel_interface_t *this,
|
|||||||
struct rtattr *rta = IFA_RTA(msg);
|
struct rtattr *rta = IFA_RTA(msg);
|
||||||
size_t rtasize = IFA_PAYLOAD (hdr);
|
size_t rtasize = IFA_PAYLOAD (hdr);
|
||||||
host_t *host = NULL;
|
host_t *host = NULL;
|
||||||
iterator_t *iterator;
|
iterator_t *ifaces, *addrs;
|
||||||
interface_entry_t *entry;
|
iface_entry_t *iface;
|
||||||
|
addr_entry_t *addr;
|
||||||
chunk_t local = chunk_empty, address = chunk_empty;
|
chunk_t local = chunk_empty, address = chunk_empty;
|
||||||
|
bool update = FALSE, found = FALSE;
|
||||||
|
|
||||||
while(RTA_OK(rta, rtasize))
|
while(RTA_OK(rta, rtasize))
|
||||||
{
|
{
|
||||||
@@ -642,7 +647,7 @@ static void process_addr(private_kernel_interface_t *this,
|
|||||||
|
|
||||||
/* For PPP interfaces, we need the IFA_LOCAL address,
|
/* For PPP interfaces, we need the IFA_LOCAL address,
|
||||||
* IFA_ADDRESS is the peers address. But IFA_LOCAL is
|
* IFA_ADDRESS is the peers address. But IFA_LOCAL is
|
||||||
* not included in all cases, so fallback to IFA_ADDRESS. */
|
* not included in all cases (IPv6?), so fallback to IFA_ADDRESS. */
|
||||||
if (local.ptr)
|
if (local.ptr)
|
||||||
{
|
{
|
||||||
host = host_create_from_chunk(msg->ifa_family, local, 0);
|
host = host_create_from_chunk(msg->ifa_family, local, 0);
|
||||||
@@ -657,61 +662,58 @@ static void process_addr(private_kernel_interface_t *this,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (hdr->nlmsg_type)
|
ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex);
|
||||||
|
while (ifaces->iterate(ifaces, (void**)&iface))
|
||||||
{
|
{
|
||||||
case RTM_NEWADDR:
|
if (iface->ifindex == msg->ifa_index)
|
||||||
{
|
{
|
||||||
iterator = this->interfaces->create_iterator_locked(this->interfaces,
|
addrs = iface->addrs->create_iterator(iface->addrs, TRUE);
|
||||||
&this->mutex);
|
while (addrs->iterate(addrs, (void**)&addr))
|
||||||
while (iterator->iterate(iterator, (void**)&entry))
|
|
||||||
{
|
{
|
||||||
if (entry->ifindex == msg->ifa_index)
|
if (host->ip_equals(host, addr->ip))
|
||||||
{
|
{
|
||||||
entry->addresses->insert_last(entry->addresses,
|
found = TRUE;
|
||||||
host->clone(host));
|
if (hdr->nlmsg_type == RTM_DELADDR)
|
||||||
|
{
|
||||||
|
addrs->remove(addrs);
|
||||||
|
addr_entry_destroy(addr);
|
||||||
|
DBG1(DBG_KNL, "%H disappeared from %s", host, iface->ifname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addrs->destroy(addrs);
|
||||||
|
|
||||||
|
if (hdr->nlmsg_type == RTM_NEWADDR)
|
||||||
|
{
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
found = TRUE;
|
||||||
|
addr = malloc_thing(addr_entry_t);
|
||||||
|
addr->ip = host->clone(host);
|
||||||
|
addr->refcount = 1;
|
||||||
|
|
||||||
|
iface->addrs->insert_last(iface->addrs, addr);
|
||||||
if (event)
|
if (event)
|
||||||
{
|
{
|
||||||
DBG1(DBG_KNL, "%H appeared on %s", host, entry->ifname);
|
DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iterator->destroy(iterator);
|
if (found && (iface->flags & IFF_UP))
|
||||||
break;
|
|
||||||
}
|
|
||||||
case RTM_DELADDR:
|
|
||||||
{
|
|
||||||
iterator = this->interfaces->create_iterator_locked(this->interfaces,
|
|
||||||
&this->mutex);
|
|
||||||
while (iterator->iterate(iterator, (void**)&entry))
|
|
||||||
{
|
{
|
||||||
if (entry->ifindex == msg->ifa_index)
|
update = TRUE;
|
||||||
{
|
|
||||||
iterator_t *addresses;
|
|
||||||
host_t *current;
|
|
||||||
|
|
||||||
addresses = entry->addresses->create_iterator(
|
|
||||||
entry->addresses, TRUE);
|
|
||||||
while (addresses->iterate(addresses, (void**)¤t))
|
|
||||||
{
|
|
||||||
if (current->equals(current, host))
|
|
||||||
{
|
|
||||||
addresses->remove(addresses);
|
|
||||||
current->destroy(current);
|
|
||||||
DBG1(DBG_KNL, "%H disappeared from %s",
|
|
||||||
host, entry->ifname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addresses->destroy(addresses);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
iterator->destroy(iterator);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
ifaces->destroy(ifaces);
|
||||||
host->destroy(host);
|
host->destroy(host);
|
||||||
|
|
||||||
|
/* send an update to all IKE_SAs */
|
||||||
|
if (update && event)
|
||||||
|
{
|
||||||
|
charon->processor->queue_job(charon->processor, (job_t*)roam_job_create());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -804,6 +806,11 @@ static job_requeue_t receive_events(private_kernel_interface_t *this)
|
|||||||
case RTM_DELLINK:
|
case RTM_DELLINK:
|
||||||
process_link(this, hdr, TRUE);
|
process_link(this, hdr, TRUE);
|
||||||
break;
|
break;
|
||||||
|
case RTM_NEWROUTE:
|
||||||
|
case RTM_DELROUTE:
|
||||||
|
charon->processor->queue_job(charon->processor,
|
||||||
|
(job_t*)roam_job_create());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -977,9 +984,9 @@ static status_t init_address_list(private_kernel_interface_t *this)
|
|||||||
struct nlmsghdr *out, *current, *in;
|
struct nlmsghdr *out, *current, *in;
|
||||||
struct rtgenmsg *msg;
|
struct rtgenmsg *msg;
|
||||||
size_t len;
|
size_t len;
|
||||||
iterator_t *i_iface, *i_addr;
|
iterator_t *ifaces, *addrs;
|
||||||
host_t *address;
|
iface_entry_t *iface;
|
||||||
interface_entry_t *entry;
|
addr_entry_t *addr;
|
||||||
|
|
||||||
DBG1(DBG_KNL, "listening on interfaces:");
|
DBG1(DBG_KNL, "listening on interfaces:");
|
||||||
|
|
||||||
@@ -1039,31 +1046,39 @@ static status_t init_address_list(private_kernel_interface_t *this)
|
|||||||
}
|
}
|
||||||
free(out);
|
free(out);
|
||||||
|
|
||||||
i_iface = this->interfaces->create_iterator_locked(this->interfaces,
|
ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex);
|
||||||
&this->mutex);
|
while (ifaces->iterate(ifaces, (void**)&iface))
|
||||||
while (i_iface->iterate(i_iface, (void**)&entry))
|
|
||||||
{
|
{
|
||||||
if (entry->flags & IFF_UP)
|
if (iface->flags & IFF_UP)
|
||||||
{
|
{
|
||||||
DBG1(DBG_KNL, " %s", entry->ifname);
|
DBG1(DBG_KNL, " %s", iface->ifname);
|
||||||
i_addr = entry->addresses->create_iterator(entry->addresses, TRUE);
|
addrs = iface->addrs->create_iterator(iface->addrs, TRUE);
|
||||||
while (i_addr->iterate(i_addr, (void**)&address))
|
while (addrs->iterate(addrs, (void**)&addr))
|
||||||
{
|
{
|
||||||
DBG1(DBG_KNL, " %H", address);
|
DBG1(DBG_KNL, " %H", addr->ip);
|
||||||
}
|
}
|
||||||
i_addr->destroy(i_addr);
|
addrs->destroy(addrs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i_iface->destroy(i_iface);
|
ifaces->destroy(ifaces);
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iterator hook to return address, not address_entry_t
|
* iterator hook to iterate over addrs
|
||||||
*/
|
*/
|
||||||
static hook_result_t hook(private_kernel_interface_t *this,
|
static hook_result_t addr_hook(private_kernel_interface_t *this,
|
||||||
interface_entry_t *in, host_t **out)
|
addr_entry_t *in, host_t **out)
|
||||||
|
{
|
||||||
|
*out = in->ip;
|
||||||
|
return HOOK_NEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* iterator hook to iterate over ifaces
|
||||||
|
*/
|
||||||
|
static hook_result_t iface_hook(private_kernel_interface_t *this,
|
||||||
|
iface_entry_t *in, host_t **out)
|
||||||
{
|
{
|
||||||
if (!(in->flags & IFF_UP))
|
if (!(in->flags & IFF_UP))
|
||||||
{ /* skip interfaces not up */
|
{ /* skip interfaces not up */
|
||||||
@@ -1072,7 +1087,9 @@ static hook_result_t hook(private_kernel_interface_t *this,
|
|||||||
|
|
||||||
if (this->hiter == NULL)
|
if (this->hiter == NULL)
|
||||||
{
|
{
|
||||||
this->hiter = in->addresses->create_iterator(in->addresses, TRUE);
|
this->hiter = in->addrs->create_iterator(in->addrs, TRUE);
|
||||||
|
this->hiter->set_iterator_hook(this->hiter,
|
||||||
|
(iterator_hook_t*)addr_hook, this);
|
||||||
}
|
}
|
||||||
while (this->hiter->iterate(this->hiter, (void**)out))
|
while (this->hiter->iterate(this->hiter, (void**)out))
|
||||||
{
|
{
|
||||||
@@ -1090,9 +1107,8 @@ static iterator_t *create_address_iterator(private_kernel_interface_t *this)
|
|||||||
{
|
{
|
||||||
iterator_t *iterator;
|
iterator_t *iterator;
|
||||||
|
|
||||||
iterator = this->interfaces->create_iterator_locked(this->interfaces,
|
iterator = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex);
|
||||||
&this->mutex);
|
iterator->set_iterator_hook(iterator, (iterator_hook_t*)iface_hook, this);
|
||||||
iterator->set_iterator_hook(iterator, (iterator_hook_t*)hook, this);
|
|
||||||
return iterator;
|
return iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1101,33 +1117,32 @@ static iterator_t *create_address_iterator(private_kernel_interface_t *this)
|
|||||||
*/
|
*/
|
||||||
static char *get_interface_name(private_kernel_interface_t *this, host_t* ip)
|
static char *get_interface_name(private_kernel_interface_t *this, host_t* ip)
|
||||||
{
|
{
|
||||||
iterator_t *iterator, *addresses;
|
iterator_t *ifaces, *addrs;
|
||||||
interface_entry_t *entry;
|
iface_entry_t *iface;
|
||||||
host_t *host;
|
addr_entry_t *addr;
|
||||||
char *name = NULL;
|
char *name = NULL;
|
||||||
|
|
||||||
DBG2(DBG_KNL, "getting interface name for %H", ip);
|
DBG2(DBG_KNL, "getting interface name for %H", ip);
|
||||||
|
|
||||||
iterator = this->interfaces->create_iterator_locked(this->interfaces,
|
ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex);
|
||||||
&this->mutex);
|
while (ifaces->iterate(ifaces, (void**)&iface))
|
||||||
while (iterator->iterate(iterator, (void**)&entry))
|
|
||||||
{
|
{
|
||||||
addresses = entry->addresses->create_iterator(entry->addresses, TRUE);
|
addrs = iface->addrs->create_iterator(iface->addrs, TRUE);
|
||||||
while (addresses->iterate(addresses, (void**)&host))
|
while (addrs->iterate(addrs, (void**)&addr))
|
||||||
{
|
{
|
||||||
if (ip->ip_equals(ip, host))
|
if (ip->ip_equals(ip, addr->ip))
|
||||||
{
|
{
|
||||||
name = strdup(entry->ifname);
|
name = strdup(iface->ifname);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addresses->destroy(addresses);
|
addrs->destroy(addrs);
|
||||||
if (name)
|
if (name)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iterator->destroy(iterator);
|
ifaces->destroy(ifaces);
|
||||||
|
|
||||||
if (name)
|
if (name)
|
||||||
{
|
{
|
||||||
@@ -1147,8 +1162,9 @@ static char *get_interface_name(private_kernel_interface_t *this, host_t* ip)
|
|||||||
static status_t get_address_by_ts(private_kernel_interface_t *this,
|
static status_t get_address_by_ts(private_kernel_interface_t *this,
|
||||||
traffic_selector_t *ts, host_t **ip)
|
traffic_selector_t *ts, host_t **ip)
|
||||||
{
|
{
|
||||||
iterator_t *iterator, *addresses;
|
iterator_t *ifaces, *addrs;
|
||||||
interface_entry_t *entry;
|
iface_entry_t *iface;
|
||||||
|
addr_entry_t *addr;
|
||||||
host_t *host;
|
host_t *host;
|
||||||
int family;
|
int family;
|
||||||
bool found = FALSE;
|
bool found = FALSE;
|
||||||
@@ -1177,27 +1193,26 @@ static status_t get_address_by_ts(private_kernel_interface_t *this,
|
|||||||
}
|
}
|
||||||
host->destroy(host);
|
host->destroy(host);
|
||||||
|
|
||||||
iterator = this->interfaces->create_iterator_locked(this->interfaces,
|
ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex);
|
||||||
&this->mutex);
|
while (ifaces->iterate(ifaces, (void**)&iface))
|
||||||
while (iterator->iterate(iterator, (void**)&entry))
|
|
||||||
{
|
{
|
||||||
addresses = entry->addresses->create_iterator(entry->addresses, TRUE);
|
addrs = iface->addrs->create_iterator(iface->addrs, TRUE);
|
||||||
while (addresses->iterate(addresses, (void**)&host))
|
while (addrs->iterate(addrs, (void**)&addr))
|
||||||
{
|
{
|
||||||
if (ts->includes(ts, host))
|
if (ts->includes(ts, addr->ip))
|
||||||
{
|
{
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
*ip = host->clone(host);
|
*ip = addr->ip->clone(addr->ip);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addresses->destroy(addresses);
|
addrs->destroy(addrs);
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iterator->destroy(iterator);
|
ifaces->destroy(ifaces);
|
||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
@@ -1213,33 +1228,32 @@ static status_t get_address_by_ts(private_kernel_interface_t *this,
|
|||||||
*/
|
*/
|
||||||
static int get_interface_index(private_kernel_interface_t *this, host_t* ip)
|
static int get_interface_index(private_kernel_interface_t *this, host_t* ip)
|
||||||
{
|
{
|
||||||
iterator_t *iterator, *addresses;
|
iterator_t *ifaces, *addrs;
|
||||||
interface_entry_t *entry;
|
iface_entry_t *iface;
|
||||||
host_t *host;
|
addr_entry_t *addr;
|
||||||
int ifindex = 0;
|
int ifindex = 0;
|
||||||
|
|
||||||
DBG2(DBG_KNL, "getting iface for %H", ip);
|
DBG2(DBG_KNL, "getting iface for %H", ip);
|
||||||
|
|
||||||
iterator = this->interfaces->create_iterator_locked(this->interfaces,
|
ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex);
|
||||||
&this->mutex);
|
while (ifaces->iterate(ifaces, (void**)&iface))
|
||||||
while (iterator->iterate(iterator, (void**)&entry))
|
|
||||||
{
|
{
|
||||||
addresses = entry->addresses->create_iterator(entry->addresses, TRUE);
|
addrs = iface->addrs->create_iterator(iface->addrs, TRUE);
|
||||||
while (addresses->iterate(addresses, (void**)&host))
|
while (addrs->iterate(addrs, (void**)&addr))
|
||||||
{
|
{
|
||||||
if (ip->ip_equals(ip, host))
|
if (ip->ip_equals(ip, addr->ip))
|
||||||
{
|
{
|
||||||
ifindex = entry->ifindex;
|
ifindex = iface->ifindex;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addresses->destroy(addresses);
|
addrs->destroy(addrs);
|
||||||
if (ifindex)
|
if (ifindex)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iterator->destroy(iterator);
|
ifaces->destroy(ifaces);
|
||||||
|
|
||||||
if (ifindex == 0)
|
if (ifindex == 0)
|
||||||
{
|
{
|
||||||
@@ -1415,7 +1429,7 @@ static host_t* get_source_addr(private_kernel_interface_t *this, host_t *dest)
|
|||||||
}
|
}
|
||||||
if (source == NULL)
|
if (source == NULL)
|
||||||
{
|
{
|
||||||
DBG1(DBG_KNL, "no route found to %H", dest);
|
DBG2(DBG_KNL, "no route found to %H", dest);
|
||||||
}
|
}
|
||||||
free(out);
|
free(out);
|
||||||
return source;
|
return source;
|
||||||
@@ -1427,110 +1441,104 @@ static host_t* get_source_addr(private_kernel_interface_t *this, host_t *dest)
|
|||||||
static status_t add_ip(private_kernel_interface_t *this,
|
static status_t add_ip(private_kernel_interface_t *this,
|
||||||
host_t *virtual_ip, host_t *iface_ip)
|
host_t *virtual_ip, host_t *iface_ip)
|
||||||
{
|
{
|
||||||
int targetif;
|
iface_entry_t *iface;
|
||||||
vip_entry_t *listed;
|
addr_entry_t *addr;
|
||||||
interface_entry_t *entry;
|
iterator_t *addrs, *ifaces;
|
||||||
iterator_t *iterator;
|
|
||||||
|
|
||||||
DBG2(DBG_KNL, "adding virtual IP %H", virtual_ip);
|
DBG2(DBG_KNL, "adding virtual IP %H", virtual_ip);
|
||||||
|
|
||||||
targetif = get_interface_index(this, iface_ip);
|
ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex);
|
||||||
if (targetif == 0)
|
while (ifaces->iterate(ifaces, (void**)&iface))
|
||||||
{
|
{
|
||||||
DBG1(DBG_KNL, "unable to add virtual IP %H, no iface found for %H",
|
bool iface_found = FALSE;
|
||||||
virtual_ip, iface_ip);
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* beware of deadlocks (e.g. send/receive packets while holding the lock) */
|
addrs = iface->addrs->create_iterator(iface->addrs, TRUE);
|
||||||
iterator = this->vips->create_iterator_locked(this->vips, &this->mutex);
|
while (addrs->iterate(addrs, (void**)&addr))
|
||||||
while (iterator->iterate(iterator, (void**)&listed))
|
|
||||||
{
|
|
||||||
if (listed->if_index == targetif &&
|
|
||||||
virtual_ip->ip_equals(virtual_ip, listed->ip))
|
|
||||||
{
|
{
|
||||||
listed->refcount++;
|
if (iface_ip->ip_equals(iface_ip, addr->ip))
|
||||||
iterator->destroy(iterator);
|
|
||||||
DBG2(DBG_KNL, "virtual IP %H already added to iface %d reusing it",
|
|
||||||
virtual_ip, targetif);
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iterator->destroy(iterator);
|
|
||||||
|
|
||||||
if (manage_ipaddr(this, RTM_NEWADDR, NLM_F_CREATE | NLM_F_EXCL,
|
|
||||||
targetif, virtual_ip) == SUCCESS)
|
|
||||||
{
|
|
||||||
listed = malloc_thing(vip_entry_t);
|
|
||||||
listed->ip = virtual_ip->clone(virtual_ip);
|
|
||||||
listed->if_index = targetif;
|
|
||||||
listed->refcount = 1;
|
|
||||||
DBG2(DBG_KNL, "virtual IP %H added to iface %d", virtual_ip, targetif);
|
|
||||||
iterator = this->interfaces->create_iterator_locked(this->interfaces,
|
|
||||||
&this->mutex);
|
|
||||||
this->vips->insert_last(this->vips, listed);
|
|
||||||
/* we add the VIP also to the cached interface list; the netlink
|
|
||||||
* event comes in asynchronous and may be to late */
|
|
||||||
while (iterator->iterate(iterator, (void**)&entry))
|
|
||||||
{
|
|
||||||
if (entry->ifindex == targetif)
|
|
||||||
{
|
{
|
||||||
entry->addresses->insert_last(entry->addresses,
|
iface_found = TRUE;
|
||||||
virtual_ip->clone(virtual_ip));
|
}
|
||||||
break;
|
else if (virtual_ip->ip_equals(virtual_ip, addr->ip))
|
||||||
|
{
|
||||||
|
addr->refcount++;
|
||||||
|
DBG2(DBG_KNL, "virtual IP %H already installed on %s",
|
||||||
|
virtual_ip, iface->ifname);
|
||||||
|
addrs->destroy(addrs);
|
||||||
|
ifaces->destroy(ifaces);
|
||||||
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iterator->destroy(iterator);
|
addrs->destroy(addrs);
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG2(DBG_KNL, "unable to add virtual IP %H to iface %d",
|
if (iface_found)
|
||||||
virtual_ip, targetif);
|
{
|
||||||
|
int ifindex = iface->ifindex;
|
||||||
|
ifaces->destroy(ifaces);
|
||||||
|
if (manage_ipaddr(this, RTM_NEWADDR, NLM_F_CREATE | NLM_F_EXCL,
|
||||||
|
ifindex, virtual_ip) == SUCCESS)
|
||||||
|
{
|
||||||
|
addr = malloc_thing(addr_entry_t);
|
||||||
|
addr->ip = virtual_ip->clone(virtual_ip);
|
||||||
|
addr->refcount = 1;
|
||||||
|
pthread_mutex_lock(&this->mutex);
|
||||||
|
iface->addrs->insert_last(iface->addrs, addr);
|
||||||
|
pthread_mutex_unlock(&this->mutex);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
DBG2(DBG_KNL, "adding virtual IP %H failed", virtual_ip);
|
||||||
|
return FAILED;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
ifaces->destroy(ifaces);
|
||||||
|
|
||||||
|
DBG2(DBG_KNL, "interface address %H not found, unable to install"
|
||||||
|
"virtual IP %H", iface_ip, virtual_ip);
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of kernel_interface_t.del_ip.
|
* Implementation of kernel_interface_t.del_ip.
|
||||||
*/
|
*/
|
||||||
static status_t del_ip(private_kernel_interface_t *this,
|
static status_t del_ip(private_kernel_interface_t *this, host_t *virtual_ip)
|
||||||
host_t *virtual_ip, host_t *iface_ip)
|
|
||||||
{
|
{
|
||||||
int targetif;
|
iface_entry_t *iface;
|
||||||
vip_entry_t *listed;
|
addr_entry_t *addr;
|
||||||
iterator_t *iterator;
|
iterator_t *addrs, *ifaces;
|
||||||
|
|
||||||
DBG2(DBG_KNL, "deleting virtual IP %H", virtual_ip);
|
DBG2(DBG_KNL, "deleting virtual IP %H", virtual_ip);
|
||||||
|
|
||||||
targetif = get_interface_index(this, iface_ip);
|
ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex);
|
||||||
if (targetif == 0)
|
while (ifaces->iterate(ifaces, (void**)&iface))
|
||||||
{
|
{
|
||||||
DBG1(DBG_KNL, "unable to delete virtual IP %H, no iface found for %H",
|
addrs = iface->addrs->create_iterator(iface->addrs, TRUE);
|
||||||
virtual_ip, iface_ip);
|
while (addrs->iterate(addrs, (void**)&addr))
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* beware of deadlocks (e.g. send/receive packets while holding the lock) */
|
|
||||||
iterator = this->vips->create_iterator_locked(this->vips, &this->mutex);
|
|
||||||
while (iterator->iterate(iterator, (void**)&listed))
|
|
||||||
{
|
|
||||||
if (listed->if_index == targetif &&
|
|
||||||
virtual_ip->ip_equals(virtual_ip, listed->ip))
|
|
||||||
{
|
{
|
||||||
listed->refcount--;
|
if (virtual_ip->ip_equals(virtual_ip, addr->ip))
|
||||||
if (listed->refcount == 0)
|
|
||||||
{
|
{
|
||||||
iterator->remove(iterator);
|
int ifindex = iface->ifindex;
|
||||||
vip_entry_destroy(listed);
|
addr->refcount--;
|
||||||
iterator->destroy(iterator);
|
if (addr->refcount == 0)
|
||||||
return manage_ipaddr(this, RTM_DELADDR, 0, targetif, virtual_ip);
|
{
|
||||||
|
addrs->remove(addrs);
|
||||||
|
addrs->destroy(addrs);
|
||||||
|
ifaces->destroy(ifaces);
|
||||||
|
addr_entry_destroy(addr);
|
||||||
|
return manage_ipaddr(this, RTM_DELADDR, 0,
|
||||||
|
ifindex, virtual_ip);
|
||||||
|
}
|
||||||
|
DBG2(DBG_KNL, "virtual IP %H used by other SAs, not deleting",
|
||||||
|
virtual_ip);
|
||||||
|
addrs->destroy(addrs);
|
||||||
|
ifaces->destroy(ifaces);
|
||||||
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
iterator->destroy(iterator);
|
|
||||||
DBG2(DBG_KNL, "virtual IP %H used by other SAs, not deleting",
|
|
||||||
virtual_ip);
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
addrs->destroy(addrs);
|
||||||
}
|
}
|
||||||
iterator->destroy(iterator);
|
ifaces->destroy(ifaces);
|
||||||
|
|
||||||
DBG2(DBG_KNL, "virtual IP %H not cached, unable to delete", virtual_ip);
|
DBG2(DBG_KNL, "virtual IP %H not cached, unable to delete", virtual_ip);
|
||||||
return FAILED;
|
return FAILED;
|
||||||
@@ -1759,10 +1767,10 @@ static status_t add_sa(private_kernel_interface_t *this,
|
|||||||
* Implementation of kernel_interface_t.update_sa.
|
* Implementation of kernel_interface_t.update_sa.
|
||||||
*/
|
*/
|
||||||
static status_t update_sa(private_kernel_interface_t *this,
|
static status_t update_sa(private_kernel_interface_t *this,
|
||||||
host_t *src, host_t *dst,
|
host_t *dst, u_int32_t spi,
|
||||||
|
protocol_id_t protocol,
|
||||||
host_t *new_src, host_t *new_dst,
|
host_t *new_src, host_t *new_dst,
|
||||||
host_diff_t src_changes, host_diff_t dst_changes,
|
host_diff_t src_changes, host_diff_t dst_changes)
|
||||||
u_int32_t spi, protocol_id_t protocol)
|
|
||||||
{
|
{
|
||||||
unsigned char request[BUFFER_SIZE];
|
unsigned char request[BUFFER_SIZE];
|
||||||
struct nlmsghdr *hdr, *out = NULL;
|
struct nlmsghdr *hdr, *out = NULL;
|
||||||
@@ -2277,9 +2285,8 @@ static void destroy(private_kernel_interface_t *this)
|
|||||||
close(this->socket_xfrm);
|
close(this->socket_xfrm);
|
||||||
close(this->socket_rt_events);
|
close(this->socket_rt_events);
|
||||||
close(this->socket_rt);
|
close(this->socket_rt);
|
||||||
this->vips->destroy(this->vips);
|
|
||||||
this->policies->destroy(this->policies);
|
this->policies->destroy(this->policies);
|
||||||
this->interfaces->destroy_function(this->interfaces, (void*)interface_entry_destroy);
|
this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2305,13 +2312,12 @@ kernel_interface_t *kernel_interface_create()
|
|||||||
this->public.create_address_iterator = (iterator_t*(*)(kernel_interface_t*))create_address_iterator;
|
this->public.create_address_iterator = (iterator_t*(*)(kernel_interface_t*))create_address_iterator;
|
||||||
this->public.get_source_addr = (host_t*(*)(kernel_interface_t*, host_t *dest))get_source_addr;
|
this->public.get_source_addr = (host_t*(*)(kernel_interface_t*, host_t *dest))get_source_addr;
|
||||||
this->public.add_ip = (status_t(*)(kernel_interface_t*,host_t*,host_t*)) add_ip;
|
this->public.add_ip = (status_t(*)(kernel_interface_t*,host_t*,host_t*)) add_ip;
|
||||||
this->public.del_ip = (status_t(*)(kernel_interface_t*,host_t*,host_t*)) del_ip;
|
this->public.del_ip = (status_t(*)(kernel_interface_t*,host_t*)) del_ip;
|
||||||
this->public.destroy = (void(*)(kernel_interface_t*)) destroy;
|
this->public.destroy = (void(*)(kernel_interface_t*)) destroy;
|
||||||
|
|
||||||
/* private members */
|
/* private members */
|
||||||
this->vips = linked_list_create();
|
|
||||||
this->policies = linked_list_create();
|
this->policies = linked_list_create();
|
||||||
this->interfaces = linked_list_create();
|
this->ifaces = linked_list_create();
|
||||||
this->hiter = NULL;
|
this->hiter = NULL;
|
||||||
this->seq = 200;
|
this->seq = 200;
|
||||||
pthread_mutex_init(&this->mutex,NULL);
|
pthread_mutex_init(&this->mutex,NULL);
|
||||||
@@ -2331,13 +2337,14 @@ kernel_interface_t *kernel_interface_create()
|
|||||||
charon->kill(charon, "unable to bind RT netlink socket");
|
charon->kill(charon, "unable to bind RT netlink socket");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create and bind RT socket for events (address/interface changes) */
|
/* create and bind RT socket for events (address/interface/route changes) */
|
||||||
this->socket_rt_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
this->socket_rt_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||||
if (this->socket_rt_events <= 0)
|
if (this->socket_rt_events <= 0)
|
||||||
{
|
{
|
||||||
charon->kill(charon, "unable to create RT event socket");
|
charon->kill(charon, "unable to create RT event socket");
|
||||||
}
|
}
|
||||||
addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_LINK;
|
addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR |
|
||||||
|
RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_ROUTE | RTMGRP_LINK;
|
||||||
if (bind(this->socket_rt_events, (struct sockaddr*)&addr, sizeof(addr)))
|
if (bind(this->socket_rt_events, (struct sockaddr*)&addr, sizeof(addr)))
|
||||||
{
|
{
|
||||||
charon->kill(charon, "unable to bind RT event socket");
|
charon->kill(charon, "unable to bind RT event socket");
|
||||||
|
|||||||
@@ -325,13 +325,11 @@ struct kernel_interface_t {
|
|||||||
*
|
*
|
||||||
* @param this calling object
|
* @param this calling object
|
||||||
* @param virtual_ip virtual ip address to assign
|
* @param virtual_ip virtual ip address to assign
|
||||||
* @param iface_ip IP of an interface to remove virtual IP from
|
|
||||||
* @return
|
* @return
|
||||||
* - SUCCESS
|
* - SUCCESS
|
||||||
* - FAILED if kernel comm failed
|
* - FAILED if kernel comm failed
|
||||||
*/
|
*/
|
||||||
status_t (*del_ip) (kernel_interface_t *this, host_t *virtual_ip,
|
status_t (*del_ip) (kernel_interface_t *this, host_t *virtual_ip);
|
||||||
host_t *iface_ip);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destroys a kernel_interface object.
|
* @brief Destroys a kernel_interface object.
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* @file roam_job.c
|
||||||
|
*
|
||||||
|
* @brief Implementation of roam_job_t.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Martin Willi
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "roam_job.h"
|
||||||
|
|
||||||
|
#include <sa/ike_sa.h>
|
||||||
|
#include <daemon.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct private_roam_job_t private_roam_job_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private data of an roam_job_t Object
|
||||||
|
*/
|
||||||
|
struct private_roam_job_t {
|
||||||
|
/**
|
||||||
|
* public roam_job_t interface
|
||||||
|
*/
|
||||||
|
roam_job_t public;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements job_t.destroy.
|
||||||
|
*/
|
||||||
|
static void destroy(private_roam_job_t *this)
|
||||||
|
{
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of job_t.execute.
|
||||||
|
*/
|
||||||
|
static void execute(private_roam_job_t *this)
|
||||||
|
{
|
||||||
|
ike_sa_t *ike_sa;
|
||||||
|
linked_list_t *list;
|
||||||
|
ike_sa_id_t *id;
|
||||||
|
iterator_t *iterator;
|
||||||
|
|
||||||
|
/* iterating over all IKE_SAs gives us no way to checkin_and_destroy
|
||||||
|
* after a DESTROY_ME, so we check out each available IKE_SA by hand. */
|
||||||
|
list = linked_list_create();
|
||||||
|
iterator = charon->ike_sa_manager->create_iterator(charon->ike_sa_manager);
|
||||||
|
while (iterator->iterate(iterator, (void**)&ike_sa))
|
||||||
|
{
|
||||||
|
id = ike_sa->get_id(ike_sa);
|
||||||
|
list->insert_last(list, id->clone(id));
|
||||||
|
}
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
|
||||||
|
while (list->remove_last(list, (void**)&id) == SUCCESS)
|
||||||
|
{
|
||||||
|
ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, id);
|
||||||
|
if (ike_sa)
|
||||||
|
{
|
||||||
|
if (ike_sa->roam(ike_sa) == DESTROY_ME)
|
||||||
|
{
|
||||||
|
charon->ike_sa_manager->checkin_and_destroy(
|
||||||
|
charon->ike_sa_manager, ike_sa);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
id->destroy(id);
|
||||||
|
}
|
||||||
|
list->destroy(list);
|
||||||
|
|
||||||
|
destroy(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Described in header
|
||||||
|
*/
|
||||||
|
roam_job_t *roam_job_create()
|
||||||
|
{
|
||||||
|
private_roam_job_t *this = malloc_thing(private_roam_job_t);
|
||||||
|
|
||||||
|
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
|
||||||
|
this->public.job_interface.execute = (void (*) (job_t *)) execute;
|
||||||
|
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
|
||||||
|
|
||||||
|
return &this->public;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* @file roam_job.h
|
||||||
|
*
|
||||||
|
* @brief Interface of roam_job_t.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Martin Willi
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ROAM_JOB_H_
|
||||||
|
#define ROAM_JOB_H_
|
||||||
|
|
||||||
|
typedef struct roam_job_t roam_job_t;
|
||||||
|
|
||||||
|
#include <library.h>
|
||||||
|
#include <sa/ike_sa_id.h>
|
||||||
|
#include <processing/jobs/job.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A job to inform IKE_SAs about changed local address setup.
|
||||||
|
*
|
||||||
|
* If a local address appears or disappears, the kernel fires this job to
|
||||||
|
* update all IKE_SAs.
|
||||||
|
*
|
||||||
|
* @b Constructors:
|
||||||
|
* - roam_job_create()
|
||||||
|
*
|
||||||
|
* @ingroup jobs
|
||||||
|
*/
|
||||||
|
struct roam_job_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* implements job_t interface
|
||||||
|
*/
|
||||||
|
job_t job_interface;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a job to inform IKE_SAs about an updated address list.
|
||||||
|
*
|
||||||
|
* @return initiate_ike_sa_job_t object
|
||||||
|
*
|
||||||
|
* @ingroup jobs
|
||||||
|
*/
|
||||||
|
roam_job_t *roam_job_create();
|
||||||
|
|
||||||
|
#endif /*ROAM_JOB_H_*/
|
||||||
|
|
||||||
@@ -88,9 +88,7 @@ send_dpd_job_t *send_dpd_job_create(ike_sa_id_t *ike_sa_id)
|
|||||||
/* interface functions */
|
/* interface functions */
|
||||||
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
|
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
|
||||||
this->public.job_interface.execute = (void (*) (job_t *)) execute;
|
this->public.job_interface.execute = (void (*) (job_t *)) execute;
|
||||||
|
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
|
||||||
/* public functions */
|
|
||||||
this->public.destroy = (void (*)(send_dpd_job_t *)) destroy;
|
|
||||||
|
|
||||||
/* private variables */
|
/* private variables */
|
||||||
this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
|
this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
|
||||||
|
|||||||
@@ -45,13 +45,6 @@ struct send_dpd_job_t {
|
|||||||
* implements job_t interface
|
* implements job_t interface
|
||||||
*/
|
*/
|
||||||
job_t job_interface;
|
job_t job_interface;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destroys an send_dpd_job_t object.
|
|
||||||
*
|
|
||||||
* @param this send_dpd_job_t object to destroy
|
|
||||||
*/
|
|
||||||
void (*destroy) (send_dpd_job_t *this);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -82,9 +82,7 @@ send_keepalive_job_t *send_keepalive_job_create(ike_sa_id_t *ike_sa_id)
|
|||||||
/* interface functions */
|
/* interface functions */
|
||||||
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
|
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
|
||||||
this->public.job_interface.execute = (void (*) (job_t *)) execute;
|
this->public.job_interface.execute = (void (*) (job_t *)) execute;
|
||||||
|
this->public.job_interface.destroy = (void (*) (job_t *)) destroy;
|
||||||
/* public functions */
|
|
||||||
this->public.destroy = (void (*)(send_keepalive_job_t *)) destroy;
|
|
||||||
|
|
||||||
/* private variables */
|
/* private variables */
|
||||||
this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
|
this->ike_sa_id = ike_sa_id->clone(ike_sa_id);
|
||||||
|
|||||||
@@ -44,13 +44,6 @@ struct send_keepalive_job_t {
|
|||||||
* implements job_t interface
|
* implements job_t interface
|
||||||
*/
|
*/
|
||||||
job_t job_interface;
|
job_t job_interface;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destroys an send_keepalive_job_t object.
|
|
||||||
*
|
|
||||||
* @param this send_keepalive_job_t object to destroy
|
|
||||||
*/
|
|
||||||
void (*destroy) (send_keepalive_job_t *this);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+180
-46
@@ -48,6 +48,7 @@
|
|||||||
#include <sa/task_manager.h>
|
#include <sa/task_manager.h>
|
||||||
#include <sa/tasks/ike_init.h>
|
#include <sa/tasks/ike_init.h>
|
||||||
#include <sa/tasks/ike_natd.h>
|
#include <sa/tasks/ike_natd.h>
|
||||||
|
#include <sa/tasks/ike_mobike.h>
|
||||||
#include <sa/tasks/ike_auth.h>
|
#include <sa/tasks/ike_auth.h>
|
||||||
#include <sa/tasks/ike_config.h>
|
#include <sa/tasks/ike_config.h>
|
||||||
#include <sa/tasks/ike_cert.h>
|
#include <sa/tasks/ike_cert.h>
|
||||||
@@ -149,6 +150,11 @@ struct private_ike_sa_t {
|
|||||||
*/
|
*/
|
||||||
ike_extension_t extensions;
|
ike_extension_t extensions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set of condition flags currently enabled for this IKE_SA
|
||||||
|
*/
|
||||||
|
ike_condition_t conditions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Linked List containing the child sa's of the current IKE_SA.
|
* Linked List containing the child sa's of the current IKE_SA.
|
||||||
*/
|
*/
|
||||||
@@ -194,16 +200,6 @@ struct private_ike_sa_t {
|
|||||||
*/
|
*/
|
||||||
chunk_t skp_verify;
|
chunk_t skp_verify;
|
||||||
|
|
||||||
/**
|
|
||||||
* NAT status of local host.
|
|
||||||
*/
|
|
||||||
bool nat_here;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NAT status of remote host.
|
|
||||||
*/
|
|
||||||
bool nat_there;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Virtual IP on local host, if any
|
* Virtual IP on local host, if any
|
||||||
*/
|
*/
|
||||||
@@ -219,6 +215,11 @@ struct private_ike_sa_t {
|
|||||||
*/
|
*/
|
||||||
linked_list_t *dns_servers;
|
linked_list_t *dns_servers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list of peers additional addresses, transmitted via MOBIKE
|
||||||
|
*/
|
||||||
|
linked_list_t *additional_addresses;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timestamps for this IKE_SA
|
* Timestamps for this IKE_SA
|
||||||
*/
|
*/
|
||||||
@@ -605,7 +606,7 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
|
|||||||
this->my_host = me->clone(me);
|
this->my_host = me->clone(me);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this->nat_here)
|
if (!(this->conditions & COND_NAT_THERE))
|
||||||
{
|
{
|
||||||
/* update without restrictions if we are not NATted */
|
/* update without restrictions if we are not NATted */
|
||||||
if (other_diff)
|
if (other_diff)
|
||||||
@@ -806,6 +807,8 @@ static status_t initiate(private_ike_sa_t *this, child_cfg_t *child_cfg)
|
|||||||
this->task_manager->queue_task(this->task_manager, task);
|
this->task_manager->queue_task(this->task_manager, task);
|
||||||
task = (task_t*)ike_config_create(&this->public, TRUE);
|
task = (task_t*)ike_config_create(&this->public, TRUE);
|
||||||
this->task_manager->queue_task(this->task_manager, task);
|
this->task_manager->queue_task(this->task_manager, task);
|
||||||
|
task = (task_t*)ike_mobike_create(&this->public, TRUE);
|
||||||
|
this->task_manager->queue_task(this->task_manager, task);
|
||||||
}
|
}
|
||||||
|
|
||||||
task = (task_t*)child_create_create(&this->public, child_cfg);
|
task = (task_t*)child_create_create(&this->public, child_cfg);
|
||||||
@@ -866,6 +869,8 @@ static status_t acquire(private_ike_sa_t *this, u_int32_t reqid)
|
|||||||
this->task_manager->queue_task(this->task_manager, task);
|
this->task_manager->queue_task(this->task_manager, task);
|
||||||
task = (task_t*)ike_config_create(&this->public, TRUE);
|
task = (task_t*)ike_config_create(&this->public, TRUE);
|
||||||
this->task_manager->queue_task(this->task_manager, task);
|
this->task_manager->queue_task(this->task_manager, task);
|
||||||
|
task = (task_t*)ike_mobike_create(&this->public, TRUE);
|
||||||
|
this->task_manager->queue_task(this->task_manager, task);
|
||||||
}
|
}
|
||||||
|
|
||||||
child_cfg = child_sa->get_config(child_sa);
|
child_cfg = child_sa->get_config(child_sa);
|
||||||
@@ -1092,6 +1097,8 @@ static status_t retransmit(private_ike_sa_t *this, u_int32_t message_id)
|
|||||||
task = (task_t*)child_create_create(&new->public, child_cfg);
|
task = (task_t*)child_create_create(&new->public, child_cfg);
|
||||||
new->task_manager->queue_task(new->task_manager, task);
|
new->task_manager->queue_task(new->task_manager, task);
|
||||||
}
|
}
|
||||||
|
task = (task_t*)ike_mobike_create(&new->public, TRUE);
|
||||||
|
new->task_manager->queue_task(new->task_manager, task);
|
||||||
new->task_manager->initiate(new->task_manager);
|
new->task_manager->initiate(new->task_manager);
|
||||||
}
|
}
|
||||||
charon->ike_sa_manager->checkin(charon->ike_sa_manager, &new->public);
|
charon->ike_sa_manager->checkin(charon->ike_sa_manager, &new->public);
|
||||||
@@ -1205,8 +1212,7 @@ static void set_virtual_ip(private_ike_sa_t *this, bool local, host_t *ip)
|
|||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "removing old virtual IP %H", this->my_virtual_ip);
|
DBG1(DBG_IKE, "removing old virtual IP %H", this->my_virtual_ip);
|
||||||
charon->kernel_interface->del_ip(charon->kernel_interface,
|
charon->kernel_interface->del_ip(charon->kernel_interface,
|
||||||
this->my_virtual_ip,
|
this->my_virtual_ip);
|
||||||
this->my_host);
|
|
||||||
this->my_virtual_ip->destroy(this->my_virtual_ip);
|
this->my_virtual_ip->destroy(this->my_virtual_ip);
|
||||||
}
|
}
|
||||||
if (charon->kernel_interface->add_ip(charon->kernel_interface, ip,
|
if (charon->kernel_interface->add_ip(charon->kernel_interface, ip,
|
||||||
@@ -1255,7 +1261,77 @@ static void enable_extension(private_ike_sa_t *this, ike_extension_t extension)
|
|||||||
*/
|
*/
|
||||||
static bool supports_extension(private_ike_sa_t *this, ike_extension_t extension)
|
static bool supports_extension(private_ike_sa_t *this, ike_extension_t extension)
|
||||||
{
|
{
|
||||||
return this->extensions & extension;
|
return (this->extensions & extension) != FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of ike_sa_t.has_condition.
|
||||||
|
*/
|
||||||
|
static bool has_condition(private_ike_sa_t *this, ike_condition_t condition)
|
||||||
|
{
|
||||||
|
return (this->conditions & condition) != FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of ike_sa_t.enable_condition.
|
||||||
|
*/
|
||||||
|
static void set_condition(private_ike_sa_t *this, ike_condition_t condition,
|
||||||
|
bool enable)
|
||||||
|
{
|
||||||
|
if (has_condition(this, condition) != enable)
|
||||||
|
{
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
switch (condition)
|
||||||
|
{
|
||||||
|
case COND_STALE:
|
||||||
|
DBG1(DBG_IKE, "no route to %H, setting IKE_SA to stale",
|
||||||
|
this->other_host);
|
||||||
|
break;
|
||||||
|
case COND_NAT_HERE:
|
||||||
|
DBG1(DBG_IKE, "local host is behind NAT, sending keep alives");
|
||||||
|
this->conditions |= COND_NAT_ANY;
|
||||||
|
send_keepalive(this);
|
||||||
|
break;
|
||||||
|
case COND_NAT_THERE:
|
||||||
|
DBG1(DBG_IKE, "remote host is behind NAT");
|
||||||
|
this->conditions |= COND_NAT_ANY;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this->conditions |= condition;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (condition)
|
||||||
|
{
|
||||||
|
case COND_STALE:
|
||||||
|
DBG1(DBG_IKE, "new route to %H found", this->other_host);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this->conditions &= ~condition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of ike_sa_t.add_additional_address.
|
||||||
|
*/
|
||||||
|
static void add_additional_address(private_ike_sa_t *this, host_t *host)
|
||||||
|
{
|
||||||
|
this->additional_addresses->insert_last(this->additional_addresses, host);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of ike_sa_t.create_additional_address_iterator.
|
||||||
|
*/
|
||||||
|
static iterator_t* create_additional_address_iterator(private_ike_sa_t *this)
|
||||||
|
{
|
||||||
|
return this->additional_addresses->create_iterator(
|
||||||
|
this->additional_addresses, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1589,6 +1665,84 @@ static status_t reestablish(private_ike_sa_t *this)
|
|||||||
return this->task_manager->initiate(this->task_manager);
|
return this->task_manager->initiate(this->task_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of ike_sa_t.roam.
|
||||||
|
*/
|
||||||
|
static status_t roam(private_ike_sa_t *this)
|
||||||
|
{
|
||||||
|
iterator_t *iterator;
|
||||||
|
host_t *me, *other;
|
||||||
|
ike_mobike_t *mobike;
|
||||||
|
|
||||||
|
/* only initiator handles address updated actively */
|
||||||
|
if (!this->ike_sa_id->is_initiator(this->ike_sa_id))
|
||||||
|
{
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
me = charon->kernel_interface->get_source_addr(charon->kernel_interface,
|
||||||
|
this->other_host);
|
||||||
|
if (me)
|
||||||
|
{
|
||||||
|
set_condition(this, COND_STALE, FALSE);
|
||||||
|
/* attachment still the same? */
|
||||||
|
if (me->ip_equals(me, this->my_host))
|
||||||
|
{
|
||||||
|
DBG2(DBG_IKE, "%H still reached through %H, no update needed",
|
||||||
|
this->other_host, me);
|
||||||
|
me->destroy(me);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
me->set_port(me, this->my_host->get_port(this->my_host));
|
||||||
|
|
||||||
|
#ifndef MOBIKE
|
||||||
|
set_my_host(this, me);
|
||||||
|
return reestablish(this);
|
||||||
|
#endif
|
||||||
|
/* our attachement changed, update if we have mobike */
|
||||||
|
if (this->extensions & EXT_MOBIKE)
|
||||||
|
{
|
||||||
|
mobike = ike_mobike_create(&this->public, TRUE);
|
||||||
|
mobike->roam(mobike, me, NULL);
|
||||||
|
this->task_manager->queue_task(this->task_manager, (task_t*)mobike);
|
||||||
|
return this->task_manager->initiate(this->task_manager);
|
||||||
|
}
|
||||||
|
/* reestablish if not */
|
||||||
|
set_my_host(this, me);
|
||||||
|
return reestablish(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* there is nothing we can do without mobike */
|
||||||
|
if (!(this->extensions & EXT_MOBIKE))
|
||||||
|
{
|
||||||
|
set_condition(this, COND_STALE, TRUE);
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
#ifndef MOBIKE
|
||||||
|
set_condition(this, COND_STALE, TRUE);
|
||||||
|
return FAILED;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* we are unable to reach the peer. Try an alternative address */
|
||||||
|
iterator = create_additional_address_iterator(this);
|
||||||
|
while (iterator->iterate(iterator, (void**)&other))
|
||||||
|
{
|
||||||
|
me = charon->kernel_interface->get_source_addr(charon->kernel_interface,
|
||||||
|
other);
|
||||||
|
if (me)
|
||||||
|
{
|
||||||
|
/* good, we have a new route. Use MOBIKE to update */
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
mobike = ike_mobike_create(&this->public, TRUE);
|
||||||
|
mobike->roam(mobike, me, other);
|
||||||
|
this->task_manager->queue_task(this->task_manager, (task_t*)mobike);
|
||||||
|
return this->task_manager->initiate(this->task_manager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of ike_sa_t.inherit.
|
* Implementation of ike_sa_t.inherit.
|
||||||
*/
|
*/
|
||||||
@@ -1640,32 +1794,6 @@ static status_t inherit(private_ike_sa_t *this, private_ike_sa_t *other)
|
|||||||
return this->task_manager->initiate(this->task_manager);
|
return this->task_manager->initiate(this->task_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of ike_sa_t.is_natt_enabled.
|
|
||||||
*/
|
|
||||||
static bool is_natt_enabled(private_ike_sa_t *this)
|
|
||||||
{
|
|
||||||
return this->nat_here || this->nat_there;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of ike_sa_t.enable_natt.
|
|
||||||
*/
|
|
||||||
static void enable_natt(private_ike_sa_t *this, bool local)
|
|
||||||
{
|
|
||||||
if (local)
|
|
||||||
{
|
|
||||||
DBG1(DBG_IKE, "local host is behind NAT, scheduling keep alives");
|
|
||||||
this->nat_here = TRUE;
|
|
||||||
send_keepalive(this);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBG1(DBG_IKE, "remote host is behind NAT");
|
|
||||||
this->nat_there = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of ike_sa_t.remove_dns_server
|
* Implementation of ike_sa_t.remove_dns_server
|
||||||
*/
|
*/
|
||||||
@@ -1818,13 +1946,16 @@ static void destroy(private_ike_sa_t *this)
|
|||||||
if (this->my_virtual_ip)
|
if (this->my_virtual_ip)
|
||||||
{
|
{
|
||||||
charon->kernel_interface->del_ip(charon->kernel_interface,
|
charon->kernel_interface->del_ip(charon->kernel_interface,
|
||||||
this->my_virtual_ip, this->my_host);
|
this->my_virtual_ip);
|
||||||
this->my_virtual_ip->destroy(this->my_virtual_ip);
|
this->my_virtual_ip->destroy(this->my_virtual_ip);
|
||||||
}
|
}
|
||||||
DESTROY_IF(this->other_virtual_ip);
|
DESTROY_IF(this->other_virtual_ip);
|
||||||
|
|
||||||
remove_dns_servers(this);
|
remove_dns_servers(this);
|
||||||
this->dns_servers->destroy_offset(this->dns_servers, offsetof(host_t, destroy));
|
this->dns_servers->destroy_offset(this->dns_servers,
|
||||||
|
offsetof(host_t, destroy));
|
||||||
|
this->additional_addresses->destroy_offset(this->additional_addresses,
|
||||||
|
offsetof(host_t, destroy));
|
||||||
|
|
||||||
DESTROY_IF(this->my_host);
|
DESTROY_IF(this->my_host);
|
||||||
DESTROY_IF(this->other_host);
|
DESTROY_IF(this->other_host);
|
||||||
@@ -1874,6 +2005,10 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
|
|||||||
this->public.set_other_ca = (void (*)(ike_sa_t*,ca_info_t*)) set_other_ca;
|
this->public.set_other_ca = (void (*)(ike_sa_t*,ca_info_t*)) set_other_ca;
|
||||||
this->public.enable_extension = (void(*)(ike_sa_t*, ike_extension_t extension))enable_extension;
|
this->public.enable_extension = (void(*)(ike_sa_t*, ike_extension_t extension))enable_extension;
|
||||||
this->public.supports_extension = (bool(*)(ike_sa_t*, ike_extension_t extension))supports_extension;
|
this->public.supports_extension = (bool(*)(ike_sa_t*, ike_extension_t extension))supports_extension;
|
||||||
|
this->public.set_condition = (void (*)(ike_sa_t*, ike_condition_t,bool)) set_condition;
|
||||||
|
this->public.has_condition = (bool (*)(ike_sa_t*,ike_condition_t)) has_condition;
|
||||||
|
this->public.create_additional_address_iterator = (iterator_t*(*)(ike_sa_t*))create_additional_address_iterator;
|
||||||
|
this->public.add_additional_address = (void(*)(ike_sa_t*, host_t *host))add_additional_address;
|
||||||
this->public.retransmit = (status_t (*)(ike_sa_t *, u_int32_t)) retransmit;
|
this->public.retransmit = (status_t (*)(ike_sa_t *, u_int32_t)) retransmit;
|
||||||
this->public.delete = (status_t (*)(ike_sa_t*))delete_;
|
this->public.delete = (status_t (*)(ike_sa_t*))delete_;
|
||||||
this->public.destroy = (void (*)(ike_sa_t*))destroy;
|
this->public.destroy = (void (*)(ike_sa_t*))destroy;
|
||||||
@@ -1890,10 +2025,9 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
|
|||||||
this->public.rekey_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t)) rekey_child_sa;
|
this->public.rekey_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t)) rekey_child_sa;
|
||||||
this->public.delete_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t)) delete_child_sa;
|
this->public.delete_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t)) delete_child_sa;
|
||||||
this->public.destroy_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t))destroy_child_sa;
|
this->public.destroy_child_sa = (status_t (*)(ike_sa_t*,protocol_id_t,u_int32_t))destroy_child_sa;
|
||||||
this->public.enable_natt = (void (*)(ike_sa_t*, bool)) enable_natt;
|
|
||||||
this->public.is_natt_enabled = (bool (*)(ike_sa_t*)) is_natt_enabled;
|
|
||||||
this->public.rekey = (status_t (*)(ike_sa_t*))rekey;
|
this->public.rekey = (status_t (*)(ike_sa_t*))rekey;
|
||||||
this->public.reestablish = (status_t (*)(ike_sa_t*))reestablish;
|
this->public.reestablish = (status_t (*)(ike_sa_t*))reestablish;
|
||||||
|
this->public.roam = (status_t(*)(ike_sa_t*))roam;
|
||||||
this->public.inherit = (status_t (*)(ike_sa_t*,ike_sa_t*))inherit;
|
this->public.inherit = (status_t (*)(ike_sa_t*,ike_sa_t*))inherit;
|
||||||
this->public.generate_message = (status_t (*)(ike_sa_t*,message_t*,packet_t**))generate_message;
|
this->public.generate_message = (status_t (*)(ike_sa_t*,message_t*,packet_t**))generate_message;
|
||||||
this->public.reset = (void (*)(ike_sa_t*))reset;
|
this->public.reset = (void (*)(ike_sa_t*))reset;
|
||||||
@@ -1911,6 +2045,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
|
|||||||
this->other_id = identification_create_from_encoding(ID_ANY, chunk_empty);
|
this->other_id = identification_create_from_encoding(ID_ANY, chunk_empty);
|
||||||
this->other_ca = NULL;
|
this->other_ca = NULL;
|
||||||
this->extensions = 0;
|
this->extensions = 0;
|
||||||
|
this->conditions = 0;
|
||||||
this->crypter_in = NULL;
|
this->crypter_in = NULL;
|
||||||
this->crypter_out = NULL;
|
this->crypter_out = NULL;
|
||||||
this->signer_in = NULL;
|
this->signer_in = NULL;
|
||||||
@@ -1919,8 +2054,6 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
|
|||||||
this->skp_verify = chunk_empty;
|
this->skp_verify = chunk_empty;
|
||||||
this->skp_build = chunk_empty;
|
this->skp_build = chunk_empty;
|
||||||
this->child_prf = NULL;
|
this->child_prf = NULL;
|
||||||
this->nat_here = FALSE;
|
|
||||||
this->nat_there = FALSE;
|
|
||||||
this->state = IKE_CREATED;
|
this->state = IKE_CREATED;
|
||||||
this->time.inbound = this->time.outbound = time(NULL);
|
this->time.inbound = this->time.outbound = time(NULL);
|
||||||
this->time.established = 0;
|
this->time.established = 0;
|
||||||
@@ -1933,6 +2066,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
|
|||||||
this->my_virtual_ip = NULL;
|
this->my_virtual_ip = NULL;
|
||||||
this->other_virtual_ip = NULL;
|
this->other_virtual_ip = NULL;
|
||||||
this->dns_servers = linked_list_create();
|
this->dns_servers = linked_list_create();
|
||||||
|
this->additional_addresses = linked_list_create();
|
||||||
this->keyingtry = 0;
|
this->keyingtry = 0;
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
|
|||||||
+86
-29
@@ -26,6 +26,7 @@
|
|||||||
#define IKE_SA_H_
|
#define IKE_SA_H_
|
||||||
|
|
||||||
typedef enum ike_extension_t ike_extension_t;
|
typedef enum ike_extension_t ike_extension_t;
|
||||||
|
typedef enum ike_condition_t ike_condition_t;
|
||||||
typedef enum ike_sa_state_t ike_sa_state_t;
|
typedef enum ike_sa_state_t ike_sa_state_t;
|
||||||
typedef struct ike_sa_t ike_sa_t;
|
typedef struct ike_sa_t ike_sa_t;
|
||||||
|
|
||||||
@@ -79,12 +80,38 @@ enum ike_extension_t {
|
|||||||
/**
|
/**
|
||||||
* peer supports NAT traversal as specified in RFC4306
|
* peer supports NAT traversal as specified in RFC4306
|
||||||
*/
|
*/
|
||||||
EXT_NATT,
|
EXT_NATT = (1<<0),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* peer supports MOBIKE (RFC4555)
|
* peer supports MOBIKE (RFC4555)
|
||||||
*/
|
*/
|
||||||
EXT_MOBIKE,
|
EXT_MOBIKE = (1<<1),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Conditions of an IKE_SA, change during its lifetime
|
||||||
|
*/
|
||||||
|
enum ike_condition_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connection is natted somewhere
|
||||||
|
*/
|
||||||
|
COND_NAT_ANY = (1<<0),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* we are behind NAT
|
||||||
|
*/
|
||||||
|
COND_NAT_HERE = (1<<1),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* other is behind NAT
|
||||||
|
*/
|
||||||
|
COND_NAT_THERE = (1<<2),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* peer is currently not reachable (due missing route, ...)
|
||||||
|
*/
|
||||||
|
COND_STALE = (1<<3),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -336,13 +363,25 @@ struct ike_sa_t {
|
|||||||
void (*set_peer_cfg) (ike_sa_t *this, peer_cfg_t *config);
|
void (*set_peer_cfg) (ike_sa_t *this, peer_cfg_t *config);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if the peer supports an extension.
|
* @brief Add an additional address for the peer.
|
||||||
|
*
|
||||||
|
* In MOBIKE, a peer may transmit additional addresses where it is
|
||||||
|
* reachable. These are stored in the IKE_SA.
|
||||||
|
* The own list of addresses is not stored, they are queried from
|
||||||
|
* the kernel when required.
|
||||||
*
|
*
|
||||||
* @param this calling object
|
* @param this calling object
|
||||||
* @param extension extension to check for support
|
* @param host host to add to list
|
||||||
* @return TRUE if peer supports it, FALSE otherwise
|
|
||||||
*/
|
*/
|
||||||
bool (*supports_extension)(ike_sa_t *this, ike_extension_t extension);
|
void (*add_additional_address)(ike_sa_t *this, host_t *host);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create an iterator over all additional addresses of the peer.
|
||||||
|
*
|
||||||
|
* @param this calling object
|
||||||
|
* @return iterator over addresses
|
||||||
|
*/
|
||||||
|
iterator_t* (*create_additional_address_iterator)(ike_sa_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enable an extension the peer supports.
|
* @brief Enable an extension the peer supports.
|
||||||
@@ -355,6 +394,33 @@ struct ike_sa_t {
|
|||||||
*/
|
*/
|
||||||
void (*enable_extension)(ike_sa_t *this, ike_extension_t extension);
|
void (*enable_extension)(ike_sa_t *this, ike_extension_t extension);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if the peer supports an extension.
|
||||||
|
*
|
||||||
|
* @param this calling object
|
||||||
|
* @param extension extension to check for support
|
||||||
|
* @return TRUE if peer supports it, FALSE otherwise
|
||||||
|
*/
|
||||||
|
bool (*supports_extension)(ike_sa_t *this, ike_extension_t extension);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable/disable a condition flag for this IKE_SA.
|
||||||
|
*
|
||||||
|
* @param this calling object
|
||||||
|
* @param condition condition to enable/disable
|
||||||
|
* @param enable TRUE to enable condition, FALSE to disable
|
||||||
|
*/
|
||||||
|
void (*set_condition) (ike_sa_t *this, ike_condition_t condition, bool enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if a condition flag is set.
|
||||||
|
*
|
||||||
|
* @param this calling object
|
||||||
|
* @param condition condition to check
|
||||||
|
* @return TRUE if condition flag set, FALSE otherwise
|
||||||
|
*/
|
||||||
|
bool (*has_condition) (ike_sa_t *this, ike_condition_t condition);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initiate a new connection.
|
* @brief Initiate a new connection.
|
||||||
*
|
*
|
||||||
@@ -424,6 +490,20 @@ struct ike_sa_t {
|
|||||||
*/
|
*/
|
||||||
status_t (*delete) (ike_sa_t *this);
|
status_t (*delete) (ike_sa_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Update IKE_SAs after network interfaces have changed.
|
||||||
|
*
|
||||||
|
* Whenever the network interface configuration changes, the kernel
|
||||||
|
* interface calls roam() on each IKE_SA. The IKE_SA then checks if
|
||||||
|
* the new network config requires changes, and handles appropriate.
|
||||||
|
* If MOBIKE is supported, addresses are updated; If not, the tunnel is
|
||||||
|
* restarted.
|
||||||
|
*
|
||||||
|
* @param
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
status_t (*roam)(ike_sa_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Processes a incoming IKEv2-Message.
|
* @brief Processes a incoming IKEv2-Message.
|
||||||
*
|
*
|
||||||
@@ -494,29 +574,6 @@ struct ike_sa_t {
|
|||||||
*/
|
*/
|
||||||
void (*send_keepalive) (ike_sa_t *this);
|
void (*send_keepalive) (ike_sa_t *this);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if NAT traversal is enabled for this IKE_SA.
|
|
||||||
*
|
|
||||||
* @param this calling object
|
|
||||||
* @return TRUE if NAT traversal enabled
|
|
||||||
*/
|
|
||||||
bool (*is_natt_enabled) (ike_sa_t *this);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Enable NAT detection for this IKE_SA.
|
|
||||||
*
|
|
||||||
* If a Network address translation is detected with
|
|
||||||
* NAT_DETECTION notifys, a SA must switch to ports
|
|
||||||
* 4500. To enable this behavior, call enable_natt().
|
|
||||||
* It is relevant which peer is NATted, this is specified
|
|
||||||
* with the "local" parameter. Call it twice when both
|
|
||||||
* are NATted.
|
|
||||||
*
|
|
||||||
* @param this calling object
|
|
||||||
* @param local TRUE, if we are NATted, FALSE if other
|
|
||||||
*/
|
|
||||||
void (*enable_natt) (ike_sa_t *this, bool local);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Derive all keys and create the transforms for IKE communication.
|
* @brief Derive all keys and create the transforms for IKE communication.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <sa/tasks/ike_init.h>
|
#include <sa/tasks/ike_init.h>
|
||||||
#include <sa/tasks/ike_natd.h>
|
#include <sa/tasks/ike_natd.h>
|
||||||
|
#include <sa/tasks/ike_mobike.h>
|
||||||
#include <sa/tasks/ike_auth.h>
|
#include <sa/tasks/ike_auth.h>
|
||||||
#include <sa/tasks/ike_cert.h>
|
#include <sa/tasks/ike_cert.h>
|
||||||
#include <sa/tasks/ike_rekey.h>
|
#include <sa/tasks/ike_rekey.h>
|
||||||
@@ -130,6 +131,11 @@ struct private_task_manager_t {
|
|||||||
* List of tasks initiated by peer
|
* List of tasks initiated by peer
|
||||||
*/
|
*/
|
||||||
linked_list_t *passive_tasks;
|
linked_list_t *passive_tasks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the task manager has been reset
|
||||||
|
*/
|
||||||
|
bool reset;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -140,7 +146,7 @@ static void flush(private_task_manager_t *this)
|
|||||||
task_t *task;
|
task_t *task;
|
||||||
|
|
||||||
this->queued_tasks->destroy_offset(this->queued_tasks,
|
this->queued_tasks->destroy_offset(this->queued_tasks,
|
||||||
offsetof(task_t, destroy));
|
offsetof(task_t, destroy));
|
||||||
this->passive_tasks->destroy_offset(this->passive_tasks,
|
this->passive_tasks->destroy_offset(this->passive_tasks,
|
||||||
offsetof(task_t, destroy));
|
offsetof(task_t, destroy));
|
||||||
|
|
||||||
@@ -274,6 +280,7 @@ static status_t build_request(private_task_manager_t *this)
|
|||||||
activate_task(this, IKE_AUTHENTICATE);
|
activate_task(this, IKE_AUTHENTICATE);
|
||||||
activate_task(this, IKE_CONFIG);
|
activate_task(this, IKE_CONFIG);
|
||||||
activate_task(this, CHILD_CREATE);
|
activate_task(this, CHILD_CREATE);
|
||||||
|
activate_task(this, IKE_MOBIKE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IKE_ESTABLISHED:
|
case IKE_ESTABLISHED:
|
||||||
@@ -307,7 +314,7 @@ static status_t build_request(private_task_manager_t *this)
|
|||||||
exchange = INFORMATIONAL;
|
exchange = INFORMATIONAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (activate_task(this, IKE_DEADPEER))
|
if (activate_task(this, IKE_DPD))
|
||||||
{
|
{
|
||||||
exchange = INFORMATIONAL;
|
exchange = INFORMATIONAL;
|
||||||
break;
|
break;
|
||||||
@@ -420,6 +427,8 @@ static status_t process_response(private_task_manager_t *this,
|
|||||||
return DESTROY_ME;
|
return DESTROY_ME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* catch if we get resetted while processing */
|
||||||
|
this->reset = FALSE;
|
||||||
iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
|
iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE);
|
||||||
while (iterator->iterate(iterator, (void*)&task))
|
while (iterator->iterate(iterator, (void*)&task))
|
||||||
{
|
{
|
||||||
@@ -439,6 +448,12 @@ static status_t process_response(private_task_manager_t *this,
|
|||||||
iterator->destroy(iterator);
|
iterator->destroy(iterator);
|
||||||
return DESTROY_ME;
|
return DESTROY_ME;
|
||||||
}
|
}
|
||||||
|
if (this->reset)
|
||||||
|
{ /* start all over again if we were reset */
|
||||||
|
this->reset = FALSE;
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
return build_request(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
iterator->destroy(iterator);
|
iterator->destroy(iterator);
|
||||||
|
|
||||||
@@ -597,6 +612,8 @@ static status_t process_request(private_task_manager_t *this,
|
|||||||
this->passive_tasks->insert_last(this->passive_tasks, task);
|
this->passive_tasks->insert_last(this->passive_tasks, task);
|
||||||
task = (task_t*)child_create_create(this->ike_sa, NULL);
|
task = (task_t*)child_create_create(this->ike_sa, NULL);
|
||||||
this->passive_tasks->insert_last(this->passive_tasks, task);
|
this->passive_tasks->insert_last(this->passive_tasks, task);
|
||||||
|
task = (task_t*)ike_mobike_create(this->ike_sa, FALSE);
|
||||||
|
this->passive_tasks->insert_last(this->passive_tasks, task);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CREATE_CHILD_SA:
|
case CREATE_CHILD_SA:
|
||||||
@@ -812,7 +829,7 @@ static void reset(private_task_manager_t *this)
|
|||||||
this->responding.packet = NULL;
|
this->responding.packet = NULL;
|
||||||
this->initiating.packet = NULL;
|
this->initiating.packet = NULL;
|
||||||
this->responding.mid = 0;
|
this->responding.mid = 0;
|
||||||
this->initiating.mid = -1;
|
this->initiating.mid = 0;
|
||||||
this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
|
this->initiating.type = EXCHANGE_TYPE_UNDEFINED;
|
||||||
|
|
||||||
/* reset active tasks */
|
/* reset active tasks */
|
||||||
@@ -822,6 +839,8 @@ static void reset(private_task_manager_t *this)
|
|||||||
task->migrate(task, this->ike_sa);
|
task->migrate(task, this->ike_sa);
|
||||||
this->queued_tasks->insert_first(this->queued_tasks, task);
|
this->queued_tasks->insert_first(this->queued_tasks, task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->reset = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -865,6 +884,7 @@ task_manager_t *task_manager_create(ike_sa_t *ike_sa)
|
|||||||
this->queued_tasks = linked_list_create();
|
this->queued_tasks = linked_list_create();
|
||||||
this->active_tasks = linked_list_create();
|
this->active_tasks = linked_list_create();
|
||||||
this->passive_tasks = linked_list_create();
|
this->passive_tasks = linked_list_create();
|
||||||
|
this->reset = FALSE;
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -297,7 +297,7 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
|
|||||||
this->mode = MODE_TUNNEL;
|
this->mode = MODE_TUNNEL;
|
||||||
DBG1(DBG_IKE, "not using tranport mode, not host-to-host");
|
DBG1(DBG_IKE, "not using tranport mode, not host-to-host");
|
||||||
}
|
}
|
||||||
else if (this->ike_sa->is_natt_enabled(this->ike_sa))
|
else if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
|
||||||
{
|
{
|
||||||
this->mode = MODE_TUNNEL;
|
this->mode = MODE_TUNNEL;
|
||||||
DBG1(DBG_IKE, "not using tranport mode, connection NATed");
|
DBG1(DBG_IKE, "not using tranport mode, connection NATed");
|
||||||
@@ -545,11 +545,10 @@ static status_t build_i(private_child_create_t *this, message_t *message)
|
|||||||
this->dh_group == MODP_NONE);
|
this->dh_group == MODP_NONE);
|
||||||
this->mode = this->config->get_mode(this->config);
|
this->mode = this->config->get_mode(this->config);
|
||||||
|
|
||||||
this->child_sa = child_sa_create(me, other,
|
this->child_sa = child_sa_create(
|
||||||
this->ike_sa->get_my_id(this->ike_sa),
|
me, other, this->ike_sa->get_my_id(this->ike_sa),
|
||||||
this->ike_sa->get_other_id(this->ike_sa),
|
this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid,
|
||||||
this->config, this->reqid,
|
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
|
||||||
this->ike_sa->is_natt_enabled(this->ike_sa));
|
|
||||||
|
|
||||||
if (this->child_sa->alloc(this->child_sa, this->proposals) != SUCCESS)
|
if (this->child_sa->alloc(this->child_sa, this->proposals) != SUCCESS)
|
||||||
{
|
{
|
||||||
@@ -660,12 +659,12 @@ static status_t build_r(private_child_create_t *this, message_t *message)
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
|
this->child_sa = child_sa_create(
|
||||||
this->ike_sa->get_other_host(this->ike_sa),
|
this->ike_sa->get_my_host(this->ike_sa),
|
||||||
this->ike_sa->get_my_id(this->ike_sa),
|
this->ike_sa->get_other_host(this->ike_sa),
|
||||||
this->ike_sa->get_other_id(this->ike_sa),
|
this->ike_sa->get_my_id(this->ike_sa),
|
||||||
this->config, this->reqid,
|
this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid,
|
||||||
this->ike_sa->is_natt_enabled(this->ike_sa));
|
this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
|
||||||
|
|
||||||
switch (select_and_install(this, no_dh))
|
switch (select_and_install(this, no_dh))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -636,7 +636,12 @@ static status_t process_i(private_ike_auth_t *this, message_t *message)
|
|||||||
case INVALID_SELECTORS:
|
case INVALID_SELECTORS:
|
||||||
/* these are errors, but are not critical as only the
|
/* these are errors, but are not critical as only the
|
||||||
* CHILD_SA won't get build, but IKE_SA establishes anyway */
|
* CHILD_SA won't get build, but IKE_SA establishes anyway */
|
||||||
break;
|
break;
|
||||||
|
case MOBIKE_SUPPORTED:
|
||||||
|
case ADDITIONAL_IP4_ADDRESS:
|
||||||
|
case ADDITIONAL_IP6_ADDRESS:
|
||||||
|
/* handled in ike_mobike task */
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
if (type < 16383)
|
if (type < 16383)
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ static status_t return_success(private_ike_dpd_t *this, message_t *message)
|
|||||||
*/
|
*/
|
||||||
static task_type_t get_type(private_ike_dpd_t *this)
|
static task_type_t get_type(private_ike_dpd_t *this)
|
||||||
{
|
{
|
||||||
return IKE_DEADPEER;
|
return IKE_DPD;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,307 @@
|
|||||||
|
/**
|
||||||
|
* @file ike_mobike.c
|
||||||
|
*
|
||||||
|
* @brief Implementation of the ike_mobike task.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Martin Willi
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ike_mobike.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <daemon.h>
|
||||||
|
#include <encoding/payloads/notify_payload.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct private_ike_mobike_t private_ike_mobike_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private members of a ike_mobike_t task.
|
||||||
|
*/
|
||||||
|
struct private_ike_mobike_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public methods and task_t interface.
|
||||||
|
*/
|
||||||
|
ike_mobike_t public;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigned IKE_SA.
|
||||||
|
*/
|
||||||
|
ike_sa_t *ike_sa;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Are we the initiator?
|
||||||
|
*/
|
||||||
|
bool initiator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* local host to roam to
|
||||||
|
*/
|
||||||
|
host_t *me;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remote host to roam to
|
||||||
|
*/
|
||||||
|
host_t *other;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* flush the IKE_SAs list of additional addresses
|
||||||
|
*/
|
||||||
|
static void flush_additional_addresses(private_ike_mobike_t *this)
|
||||||
|
{
|
||||||
|
iterator_t *iterator;
|
||||||
|
host_t *host;
|
||||||
|
|
||||||
|
iterator = this->ike_sa->create_additional_address_iterator(this->ike_sa);
|
||||||
|
while (iterator->iterate(iterator, (void**)&host))
|
||||||
|
{
|
||||||
|
iterator->remove(iterator);
|
||||||
|
host->destroy(host);
|
||||||
|
}
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read notifys from message and evaluate them
|
||||||
|
*/
|
||||||
|
static void process_payloads(private_ike_mobike_t *this, message_t *message)
|
||||||
|
{
|
||||||
|
iterator_t *iterator;
|
||||||
|
payload_t *payload;
|
||||||
|
bool first = TRUE;
|
||||||
|
|
||||||
|
iterator = message->get_payload_iterator(message);
|
||||||
|
while (iterator->iterate(iterator, (void**)&payload))
|
||||||
|
{
|
||||||
|
int family = AF_INET;
|
||||||
|
notify_payload_t *notify;
|
||||||
|
chunk_t data;
|
||||||
|
host_t *host;
|
||||||
|
|
||||||
|
if (payload->get_type(payload) != NOTIFY)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
notify = (notify_payload_t*)payload;
|
||||||
|
switch (notify->get_notify_type(notify))
|
||||||
|
{
|
||||||
|
case MOBIKE_SUPPORTED:
|
||||||
|
{
|
||||||
|
DBG2(DBG_IKE, "peer supports MOBIKE");
|
||||||
|
this->ike_sa->enable_extension(this->ike_sa, EXT_MOBIKE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ADDITIONAL_IP6_ADDRESS:
|
||||||
|
{
|
||||||
|
family = AF_INET6;
|
||||||
|
/* fall through */
|
||||||
|
}
|
||||||
|
case ADDITIONAL_IP4_ADDRESS:
|
||||||
|
{
|
||||||
|
if (first)
|
||||||
|
{ /* an ADDITIONAL_*_ADDRESS means replace, so flush once */
|
||||||
|
flush_additional_addresses(this);
|
||||||
|
}
|
||||||
|
data = notify->get_notification_data(notify);
|
||||||
|
host = host_create_from_chunk(family, data, 0);
|
||||||
|
DBG2(DBG_IKE, "got additional MOBIKE peer address: %H", host);
|
||||||
|
this->ike_sa->add_additional_address(this->ike_sa, host);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NO_ADDITIONAL_ADDRESSES:
|
||||||
|
{
|
||||||
|
flush_additional_addresses(this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add ADDITIONAL_*_ADDRESS notifys depending on our address list
|
||||||
|
*/
|
||||||
|
static void build_address_list(private_ike_mobike_t *this, message_t *message)
|
||||||
|
{
|
||||||
|
iterator_t *iterator;
|
||||||
|
host_t *host, *me;
|
||||||
|
notify_type_t type;
|
||||||
|
bool additional = FALSE;
|
||||||
|
|
||||||
|
me = this->ike_sa->get_my_host(this->ike_sa);
|
||||||
|
iterator = charon->kernel_interface->create_address_iterator(
|
||||||
|
charon->kernel_interface);
|
||||||
|
while (iterator->iterate(iterator, (void**)&host))
|
||||||
|
{
|
||||||
|
if (me->ip_equals(me, host))
|
||||||
|
{ /* "ADDITIONAL" means do not include IKE_SAs host */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (host->get_family(host))
|
||||||
|
{
|
||||||
|
case AF_INET:
|
||||||
|
type = ADDITIONAL_IP4_ADDRESS;
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
type = ADDITIONAL_IP6_ADDRESS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
message->add_notify(message, FALSE, type, host->get_address(host));
|
||||||
|
additional = TRUE;
|
||||||
|
}
|
||||||
|
if (!additional)
|
||||||
|
{
|
||||||
|
message->add_notify(message, FALSE, NO_ADDITIONAL_ADDRESSES, chunk_empty);
|
||||||
|
}
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of task_t.process for initiator
|
||||||
|
*/
|
||||||
|
static status_t build_i(private_ike_mobike_t *this, message_t *message)
|
||||||
|
{
|
||||||
|
if (message->get_exchange_type(message) == IKE_AUTH &&
|
||||||
|
message->get_payload(message, SECURITY_ASSOCIATION))
|
||||||
|
{
|
||||||
|
message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
|
||||||
|
build_address_list(this, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NEED_MORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of task_t.process for responder
|
||||||
|
*/
|
||||||
|
static status_t process_r(private_ike_mobike_t *this, message_t *message)
|
||||||
|
{
|
||||||
|
process_payloads(this, message);
|
||||||
|
|
||||||
|
return NEED_MORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of task_t.build for responder
|
||||||
|
*/
|
||||||
|
static status_t build_r(private_ike_mobike_t *this, message_t *message)
|
||||||
|
{
|
||||||
|
if (message->get_exchange_type(message) == IKE_AUTH &&
|
||||||
|
message->get_payload(message, SECURITY_ASSOCIATION))
|
||||||
|
{
|
||||||
|
if (this->ike_sa->supports_extension(this->ike_sa, EXT_MOBIKE))
|
||||||
|
{
|
||||||
|
message->add_notify(message, FALSE, MOBIKE_SUPPORTED, chunk_empty);
|
||||||
|
build_address_list(this, message);
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
return NEED_MORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of task_t.process for initiator
|
||||||
|
*/
|
||||||
|
static status_t process_i(private_ike_mobike_t *this, message_t *message)
|
||||||
|
{
|
||||||
|
if (message->get_exchange_type(message) == IKE_AUTH &&
|
||||||
|
message->get_payload(message, SECURITY_ASSOCIATION))
|
||||||
|
{
|
||||||
|
process_payloads(this, message);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
return NEED_MORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of ike_mobike_t.roam.
|
||||||
|
*/
|
||||||
|
static void roam(private_ike_mobike_t *this, host_t *me, host_t *other)
|
||||||
|
{
|
||||||
|
this->me = me;
|
||||||
|
this->other = other;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of task_t.get_type
|
||||||
|
*/
|
||||||
|
static task_type_t get_type(private_ike_mobike_t *this)
|
||||||
|
{
|
||||||
|
return IKE_MOBIKE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of task_t.migrate
|
||||||
|
*/
|
||||||
|
static void migrate(private_ike_mobike_t *this, ike_sa_t *ike_sa)
|
||||||
|
{
|
||||||
|
DESTROY_IF(this->me);
|
||||||
|
DESTROY_IF(this->other);
|
||||||
|
this->ike_sa = ike_sa;
|
||||||
|
this->me = NULL;
|
||||||
|
this->other = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of task_t.destroy
|
||||||
|
*/
|
||||||
|
static void destroy(private_ike_mobike_t *this)
|
||||||
|
{
|
||||||
|
DESTROY_IF(this->me);
|
||||||
|
DESTROY_IF(this->other);
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Described in header.
|
||||||
|
*/
|
||||||
|
ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator)
|
||||||
|
{
|
||||||
|
private_ike_mobike_t *this = malloc_thing(private_ike_mobike_t);
|
||||||
|
|
||||||
|
this->public.roam = (void(*)(ike_mobike_t*, host_t *, host_t *))roam;
|
||||||
|
this->public.task.get_type = (task_type_t(*)(task_t*))get_type;
|
||||||
|
this->public.task.migrate = (void(*)(task_t*,ike_sa_t*))migrate;
|
||||||
|
this->public.task.destroy = (void(*)(task_t*))destroy;
|
||||||
|
|
||||||
|
if (initiator)
|
||||||
|
{
|
||||||
|
this->public.task.build = (status_t(*)(task_t*,message_t*))build_i;
|
||||||
|
this->public.task.process = (status_t(*)(task_t*,message_t*))process_i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->public.task.build = (status_t(*)(task_t*,message_t*))build_r;
|
||||||
|
this->public.task.process = (status_t(*)(task_t*,message_t*))process_r;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->ike_sa = ike_sa;
|
||||||
|
this->initiator = initiator;
|
||||||
|
this->me = NULL;
|
||||||
|
this->other = NULL;
|
||||||
|
|
||||||
|
return &this->public;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* @file ike_mobike.h
|
||||||
|
*
|
||||||
|
* @brief Interface ike_mobike_t.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Martin Willi
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IKE_MOBIKE_H_
|
||||||
|
#define IKE_MOBIKE_H_
|
||||||
|
|
||||||
|
typedef struct ike_mobike_t ike_mobike_t;
|
||||||
|
|
||||||
|
#include <library.h>
|
||||||
|
#include <sa/ike_sa.h>
|
||||||
|
#include <sa/tasks/task.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Task of type ike_mobike, detects and handles MOBIKE extension.
|
||||||
|
*
|
||||||
|
* The MOBIKE extension is defined in RFC4555. It allows to update IKE
|
||||||
|
* and IPsec tunnel addresses.
|
||||||
|
* This tasks handles the MOBIKE_SUPPORTED notify exchange to detect MOBIKE
|
||||||
|
* support, allows the exchange of ADDITIONAL_*_ADDRESS to exchange additional
|
||||||
|
* endpoints and handles the UPDATE_SA_ADDRESS notify to finally update
|
||||||
|
* endpoints.
|
||||||
|
*
|
||||||
|
* @b Constructors:
|
||||||
|
* - ike_mobike_create()
|
||||||
|
*
|
||||||
|
* @ingroup tasks
|
||||||
|
*/
|
||||||
|
struct ike_mobike_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the task_t interface
|
||||||
|
*/
|
||||||
|
task_t task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Use the task to roam to other addresses.
|
||||||
|
*
|
||||||
|
* Supplied hosts may be NULL to reuse existing IKE_SA hosts.
|
||||||
|
*
|
||||||
|
* @param this calling object
|
||||||
|
* @param me local host to roam to, or NULL
|
||||||
|
* @param other remote host to roam to, or NULL
|
||||||
|
*/
|
||||||
|
void (*roam)(ike_mobike_t *this, host_t *me, host_t *other);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new ike_mobike task.
|
||||||
|
*
|
||||||
|
* @param ike_sa IKE_SA this task works for
|
||||||
|
* @param initiator TRUE if taks is initiated by us
|
||||||
|
* @return ike_mobike task to handle by the task_manager
|
||||||
|
*/
|
||||||
|
ike_mobike_t *ike_mobike_create(ike_sa_t *ike_sa, bool initiator);
|
||||||
|
|
||||||
|
#endif /* IKE_MOBIKE_H_ */
|
||||||
|
|
||||||
@@ -207,11 +207,11 @@ static void process_payloads(private_ike_natd_t *this, message_t *message)
|
|||||||
|
|
||||||
if (!this->dst_matched)
|
if (!this->dst_matched)
|
||||||
{
|
{
|
||||||
this->ike_sa->enable_natt(this->ike_sa, TRUE);
|
this->ike_sa->set_condition(this->ike_sa, COND_NAT_HERE, TRUE);
|
||||||
}
|
}
|
||||||
if (!this->src_matched)
|
if (!this->src_matched)
|
||||||
{
|
{
|
||||||
this->ike_sa->enable_natt(this->ike_sa, FALSE);
|
this->ike_sa->set_condition(this->ike_sa, COND_NAT_THERE, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,7 +223,7 @@ static status_t process_i(private_ike_natd_t *this, message_t *message)
|
|||||||
{
|
{
|
||||||
process_payloads(this, message);
|
process_payloads(this, message);
|
||||||
|
|
||||||
if (this->ike_sa->is_natt_enabled(this->ike_sa))
|
if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
|
||||||
{
|
{
|
||||||
host_t *me, *other;
|
host_t *me, *other;
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,8 @@ static status_t process_i(private_ike_reauth_t *this, message_t *message)
|
|||||||
new->set_peer_cfg(new, this->ike_sa->get_peer_cfg(this->ike_sa));
|
new->set_peer_cfg(new, this->ike_sa->get_peer_cfg(this->ike_sa));
|
||||||
host = this->ike_sa->get_other_host(this->ike_sa);
|
host = this->ike_sa->get_other_host(this->ike_sa);
|
||||||
new->set_other_host(new, host->clone(host));
|
new->set_other_host(new, host->clone(host));
|
||||||
|
host = this->ike_sa->get_my_host(this->ike_sa);
|
||||||
|
new->set_my_host(new, host->clone(host));
|
||||||
/* if we already have a virtual IP, we reuse it */
|
/* if we already have a virtual IP, we reuse it */
|
||||||
host = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
|
host = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
|
||||||
if (host)
|
if (host)
|
||||||
|
|||||||
@@ -25,14 +25,16 @@
|
|||||||
ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
|
ENUM(task_type_names, IKE_INIT, CHILD_REKEY,
|
||||||
"IKE_INIT",
|
"IKE_INIT",
|
||||||
"IKE_NATD",
|
"IKE_NATD",
|
||||||
|
"IKE_MOBIKE",
|
||||||
"IKE_AUTHENTICATE",
|
"IKE_AUTHENTICATE",
|
||||||
"IKE_CERT",
|
"IKE_CERT",
|
||||||
"IKE_CONFIG",
|
"IKE_CONFIG",
|
||||||
"IKE_DPD",
|
|
||||||
"IKE_REKEY",
|
"IKE_REKEY",
|
||||||
|
"IKE_REAUTH",
|
||||||
"IKE_DELETE",
|
"IKE_DELETE",
|
||||||
"IKE_DEADPEER",
|
"IKE_DPD",
|
||||||
"CHILD_CREATE",
|
"CHILD_CREATE",
|
||||||
"CHILD_DELETE",
|
"CHILD_DELETE",
|
||||||
"CHILD_REKEY",
|
"CHILD_REKEY",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -40,14 +40,14 @@ enum task_type_t {
|
|||||||
IKE_INIT,
|
IKE_INIT,
|
||||||
/** detect NAT situation */
|
/** detect NAT situation */
|
||||||
IKE_NATD,
|
IKE_NATD,
|
||||||
|
/** handle MOBIKE stuff */
|
||||||
|
IKE_MOBIKE,
|
||||||
/** authenticate the initiated IKE_SA */
|
/** authenticate the initiated IKE_SA */
|
||||||
IKE_AUTHENTICATE,
|
IKE_AUTHENTICATE,
|
||||||
/** exchange certificates and requests */
|
/** exchange certificates and requests */
|
||||||
IKE_CERT,
|
IKE_CERT,
|
||||||
/** Configuration payloads, virtual IP and such */
|
/** Configuration payloads, virtual IP and such */
|
||||||
IKE_CONFIG,
|
IKE_CONFIG,
|
||||||
/** DPD detection */
|
|
||||||
IKE_DEADPEER,
|
|
||||||
/** rekey an IKE_SA */
|
/** rekey an IKE_SA */
|
||||||
IKE_REKEY,
|
IKE_REKEY,
|
||||||
/** reestablish a complete IKE_SA */
|
/** reestablish a complete IKE_SA */
|
||||||
|
|||||||
Reference in New Issue
Block a user