diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am index b0a3c5668..9812a32ae 100644 --- a/src/charon/Makefile.am +++ b/src/charon/Makefile.am @@ -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/send_dpd_job.c processing/jobs/send_dpd_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/processor.c processing/processor.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_init.c sa/tasks/ike_init.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_reauth.c sa/tasks/ike_reauth.h \ sa/tasks/task.c sa/tasks/task.h diff --git a/src/charon/encoding/payloads/notify_payload.c b/src/charon/encoding/payloads/notify_payload.c index a04901a90..ca92fc1bf 100644 --- a/src/charon/encoding/payloads/notify_payload.c +++ b/src/charon/encoding/payloads/notify_payload.c @@ -189,6 +189,8 @@ encoding_rule_t notify_payload_encodings[] = { */ static status_t verify(private_notify_payload_t *this) { + bool bad_length = FALSE; + switch (this->protocol_id) { case PROTO_NONE: @@ -205,30 +207,9 @@ static status_t verify(private_notify_payload_t *this) { case INVALID_KE_PAYLOAD: { - /* check notification data */ - diffie_hellman_group_t dh_group; if (this->notification_data.len != 2) { - DBG1(DBG_ENC, "invalid notify data length for %N (%d)", - 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; + bad_length = TRUE; } break; } @@ -237,9 +218,7 @@ static status_t verify(private_notify_payload_t *this) { if (this->notification_data.len != HASH_SIZE_SHA1) { - DBG1(DBG_ENC, "invalid %N notify length", - notify_type_names, this->notify_type); - return FAILED; + bad_length = TRUE; } break; } @@ -249,9 +228,23 @@ static status_t verify(private_notify_payload_t *this) { if (this->notification_data.len != 0) { - DBG1(DBG_ENC, "invalid %N notify", - notify_type_names, this->notify_type); - return FAILED; + bad_length = TRUE; + } + 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; } @@ -259,6 +252,13 @@ static status_t verify(private_notify_payload_t *this) /* TODO: verify */ 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; } diff --git a/src/charon/kernel/kernel_interface.c b/src/charon/kernel/kernel_interface.c index 73fd513b1..9847f30a3 100644 --- a/src/charon/kernel/kernel_interface.c +++ b/src/charon/kernel/kernel_interface.c @@ -49,6 +49,7 @@ #include #include #include +#include /** kernel level protocol identifiers */ #define KERNEL_ESP 50 @@ -217,37 +218,35 @@ struct policy_entry_t { 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 { - /** Index of the interface the ip is bound to */ - u_int8_t if_index; +struct addr_entry_t { /** The ip address */ host_t *ip; - /** Number of times this IP is used */ + /** Number of times this IP is used, if virtual */ 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); 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 */ int ifindex; @@ -259,15 +258,15 @@ struct interface_entry_t { u_int flags; /** list of addresses as host_t */ - linked_list_t *addresses; + linked_list_t *addrs; }; /** * 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); } @@ -288,19 +287,14 @@ struct private_kernel_interface_t { pthread_mutex_t mutex; /** - * List of installed policies (kernel_entry_t) + * List of installed policies (policy_entry_t) */ 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; - - /** - * Cached list of interfaces and its adresses (interface_entry_t) - */ - linked_list_t *interfaces; + linked_list_t *ifaces; /** * iterator used in hook() @@ -529,8 +523,9 @@ static void process_link(private_kernel_interface_t *this, struct rtattr *rta = IFLA_RTA(msg); size_t rtasize = IFLA_PAYLOAD (hdr); iterator_t *iterator; - interface_entry_t *current, *entry = NULL; + iface_entry_t *current, *entry = NULL; char *name = NULL; + bool update = FALSE; while(RTA_OK(rta, rtasize)) { @@ -555,8 +550,8 @@ static void process_link(private_kernel_interface_t *this, { /* ignore loopback interfaces */ break; } - iterator = this->interfaces->create_iterator_locked(this->interfaces, - &this->mutex); + iterator = this->ifaces->create_iterator_locked(this->ifaces, + &this->mutex); while (iterator->iterate(iterator, (void**)¤t)) { if (current->ifindex == msg->ifi_index) @@ -567,11 +562,11 @@ static void process_link(private_kernel_interface_t *this, } if (!entry) { - entry = malloc_thing(interface_entry_t); + entry = malloc_thing(iface_entry_t); entry->ifindex = msg->ifi_index; entry->flags = 0; - entry->addresses = linked_list_create(); - this->interfaces->insert_last(this->interfaces, entry); + entry->addrs = linked_list_create(); + this->ifaces->insert_last(this->ifaces, entry); } memcpy(entry->ifname, name, IFNAMSIZ); 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)) { + update = TRUE; DBG1(DBG_KNL, "interface %s activated", name); } if ((entry->flags & IFF_UP) && !(msg->ifi_flags & IFF_UP)) { + update = TRUE; DBG1(DBG_KNL, "interface %s deactivated", name); } } @@ -592,8 +589,8 @@ static void process_link(private_kernel_interface_t *this, } case RTM_DELLINK: { - iterator = this->interfaces->create_iterator_locked(this->interfaces, - &this->mutex); + iterator = this->ifaces->create_iterator_locked(this->ifaces, + &this->mutex); while (iterator->iterate(iterator, (void**)¤t)) { if (current->ifindex == msg->ifi_index) @@ -608,6 +605,12 @@ static void process_link(private_kernel_interface_t *this, 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); size_t rtasize = IFA_PAYLOAD (hdr); host_t *host = NULL; - iterator_t *iterator; - interface_entry_t *entry; + iterator_t *ifaces, *addrs; + iface_entry_t *iface; + addr_entry_t *addr; chunk_t local = chunk_empty, address = chunk_empty; + bool update = FALSE, found = FALSE; 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, * 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) { host = host_create_from_chunk(msg->ifa_family, local, 0); @@ -657,61 +662,58 @@ static void process_addr(private_kernel_interface_t *this, 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, - &this->mutex); - while (iterator->iterate(iterator, (void**)&entry)) + addrs = iface->addrs->create_iterator(iface->addrs, TRUE); + while (addrs->iterate(addrs, (void**)&addr)) { - if (entry->ifindex == msg->ifa_index) + if (host->ip_equals(host, addr->ip)) { - entry->addresses->insert_last(entry->addresses, - host->clone(host)); + found = TRUE; + 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) { - DBG1(DBG_KNL, "%H appeared on %s", host, entry->ifname); + DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname); } - break; } } - iterator->destroy(iterator); - break; - } - case RTM_DELADDR: - { - iterator = this->interfaces->create_iterator_locked(this->interfaces, - &this->mutex); - while (iterator->iterate(iterator, (void**)&entry)) + if (found && (iface->flags & IFF_UP)) { - if (entry->ifindex == msg->ifa_index) - { - 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); - } + update = TRUE; } - iterator->destroy(iterator); break; } - default: - break; } + ifaces->destroy(ifaces); 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: process_link(this, hdr, TRUE); break; + case RTM_NEWROUTE: + case RTM_DELROUTE: + charon->processor->queue_job(charon->processor, + (job_t*)roam_job_create()); + break; default: break; } @@ -977,9 +984,9 @@ static status_t init_address_list(private_kernel_interface_t *this) struct nlmsghdr *out, *current, *in; struct rtgenmsg *msg; size_t len; - iterator_t *i_iface, *i_addr; - host_t *address; - interface_entry_t *entry; + iterator_t *ifaces, *addrs; + iface_entry_t *iface; + addr_entry_t *addr; DBG1(DBG_KNL, "listening on interfaces:"); @@ -1039,31 +1046,39 @@ static status_t init_address_list(private_kernel_interface_t *this) } free(out); - i_iface = this->interfaces->create_iterator_locked(this->interfaces, - &this->mutex); - while (i_iface->iterate(i_iface, (void**)&entry)) + ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex); + while (ifaces->iterate(ifaces, (void**)&iface)) { - if (entry->flags & IFF_UP) + if (iface->flags & IFF_UP) { - DBG1(DBG_KNL, " %s", entry->ifname); - i_addr = entry->addresses->create_iterator(entry->addresses, TRUE); - while (i_addr->iterate(i_addr, (void**)&address)) + DBG1(DBG_KNL, " %s", iface->ifname); + addrs = iface->addrs->create_iterator(iface->addrs, TRUE); + 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; } /** - * 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, - interface_entry_t *in, host_t **out) +static hook_result_t addr_hook(private_kernel_interface_t *this, + 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)) { /* skip interfaces not up */ @@ -1072,7 +1087,9 @@ static hook_result_t hook(private_kernel_interface_t *this, 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)) { @@ -1090,9 +1107,8 @@ static iterator_t *create_address_iterator(private_kernel_interface_t *this) { iterator_t *iterator; - iterator = this->interfaces->create_iterator_locked(this->interfaces, - &this->mutex); - iterator->set_iterator_hook(iterator, (iterator_hook_t*)hook, this); + iterator = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex); + iterator->set_iterator_hook(iterator, (iterator_hook_t*)iface_hook, this); 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) { - iterator_t *iterator, *addresses; - interface_entry_t *entry; - host_t *host; + iterator_t *ifaces, *addrs; + iface_entry_t *iface; + addr_entry_t *addr; char *name = NULL; DBG2(DBG_KNL, "getting interface name for %H", ip); - iterator = this->interfaces->create_iterator_locked(this->interfaces, - &this->mutex); - while (iterator->iterate(iterator, (void**)&entry)) + ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex); + while (ifaces->iterate(ifaces, (void**)&iface)) { - addresses = entry->addresses->create_iterator(entry->addresses, TRUE); - while (addresses->iterate(addresses, (void**)&host)) + addrs = iface->addrs->create_iterator(iface->addrs, TRUE); + 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; } } - addresses->destroy(addresses); + addrs->destroy(addrs); if (name) { break; } } - iterator->destroy(iterator); + ifaces->destroy(ifaces); 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, traffic_selector_t *ts, host_t **ip) { - iterator_t *iterator, *addresses; - interface_entry_t *entry; + iterator_t *ifaces, *addrs; + iface_entry_t *iface; + addr_entry_t *addr; host_t *host; int family; bool found = FALSE; @@ -1177,27 +1193,26 @@ static status_t get_address_by_ts(private_kernel_interface_t *this, } host->destroy(host); - iterator = this->interfaces->create_iterator_locked(this->interfaces, - &this->mutex); - while (iterator->iterate(iterator, (void**)&entry)) + ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex); + while (ifaces->iterate(ifaces, (void**)&iface)) { - addresses = entry->addresses->create_iterator(entry->addresses, TRUE); - while (addresses->iterate(addresses, (void**)&host)) + addrs = iface->addrs->create_iterator(iface->addrs, TRUE); + while (addrs->iterate(addrs, (void**)&addr)) { - if (ts->includes(ts, host)) + if (ts->includes(ts, addr->ip)) { found = TRUE; - *ip = host->clone(host); + *ip = addr->ip->clone(addr->ip); break; } } - addresses->destroy(addresses); + addrs->destroy(addrs); if (found) { break; } } - iterator->destroy(iterator); + ifaces->destroy(ifaces); 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) { - iterator_t *iterator, *addresses; - interface_entry_t *entry; - host_t *host; + iterator_t *ifaces, *addrs; + iface_entry_t *iface; + addr_entry_t *addr; int ifindex = 0; DBG2(DBG_KNL, "getting iface for %H", ip); - iterator = this->interfaces->create_iterator_locked(this->interfaces, - &this->mutex); - while (iterator->iterate(iterator, (void**)&entry)) + ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex); + while (ifaces->iterate(ifaces, (void**)&iface)) { - addresses = entry->addresses->create_iterator(entry->addresses, TRUE); - while (addresses->iterate(addresses, (void**)&host)) + addrs = iface->addrs->create_iterator(iface->addrs, TRUE); + 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; } } - addresses->destroy(addresses); + addrs->destroy(addrs); if (ifindex) { break; } } - iterator->destroy(iterator); + ifaces->destroy(ifaces); if (ifindex == 0) { @@ -1415,7 +1429,7 @@ static host_t* get_source_addr(private_kernel_interface_t *this, host_t *dest) } if (source == NULL) { - DBG1(DBG_KNL, "no route found to %H", dest); + DBG2(DBG_KNL, "no route found to %H", dest); } free(out); return source; @@ -1427,111 +1441,105 @@ static host_t* get_source_addr(private_kernel_interface_t *this, host_t *dest) static status_t add_ip(private_kernel_interface_t *this, host_t *virtual_ip, host_t *iface_ip) { - int targetif; - vip_entry_t *listed; - interface_entry_t *entry; - iterator_t *iterator; + iface_entry_t *iface; + addr_entry_t *addr; + iterator_t *addrs, *ifaces; DBG2(DBG_KNL, "adding virtual IP %H", virtual_ip); - - targetif = get_interface_index(this, iface_ip); - if (targetif == 0) + + ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex); + while (ifaces->iterate(ifaces, (void**)&iface)) { - DBG1(DBG_KNL, "unable to add virtual IP %H, no iface found for %H", - virtual_ip, iface_ip); - 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)) + bool iface_found = FALSE; + + addrs = iface->addrs->create_iterator(iface->addrs, TRUE); + while (addrs->iterate(addrs, (void**)&addr)) { - listed->refcount++; - 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) + if (iface_ip->ip_equals(iface_ip, addr->ip)) { - entry->addresses->insert_last(entry->addresses, - virtual_ip->clone(virtual_ip)); - break; + iface_found = TRUE; + } + 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); - return SUCCESS; + addrs->destroy(addrs); + + if (iface_found) + { + 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, "unable to add virtual IP %H to iface %d", - virtual_ip, targetif); + DBG2(DBG_KNL, "interface address %H not found, unable to install" + "virtual IP %H", iface_ip, virtual_ip); return FAILED; } /** * Implementation of kernel_interface_t.del_ip. */ -static status_t del_ip(private_kernel_interface_t *this, - host_t *virtual_ip, host_t *iface_ip) +static status_t del_ip(private_kernel_interface_t *this, host_t *virtual_ip) { - int targetif; - vip_entry_t *listed; - iterator_t *iterator; + iface_entry_t *iface; + addr_entry_t *addr; + iterator_t *addrs, *ifaces; DBG2(DBG_KNL, "deleting virtual IP %H", virtual_ip); - - targetif = get_interface_index(this, iface_ip); - if (targetif == 0) + + ifaces = this->ifaces->create_iterator_locked(this->ifaces, &this->mutex); + while (ifaces->iterate(ifaces, (void**)&iface)) { - DBG1(DBG_KNL, "unable to delete virtual IP %H, no iface found for %H", - virtual_ip, iface_ip); - 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)) + addrs = iface->addrs->create_iterator(iface->addrs, TRUE); + while (addrs->iterate(addrs, (void**)&addr)) { - listed->refcount--; - if (listed->refcount == 0) + if (virtual_ip->ip_equals(virtual_ip, addr->ip)) { - iterator->remove(iterator); - vip_entry_destroy(listed); - iterator->destroy(iterator); - return manage_ipaddr(this, RTM_DELADDR, 0, targetif, virtual_ip); + int ifindex = iface->ifindex; + addr->refcount--; + if (addr->refcount == 0) + { + 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); return FAILED; } @@ -1759,10 +1767,10 @@ static status_t add_sa(private_kernel_interface_t *this, * Implementation of kernel_interface_t.update_sa. */ static status_t update_sa(private_kernel_interface_t *this, - host_t *src, host_t *dst, - host_t *new_src, host_t *new_dst, - host_diff_t src_changes, host_diff_t dst_changes, - u_int32_t spi, protocol_id_t protocol) + host_t *dst, u_int32_t spi, + protocol_id_t protocol, + host_t *new_src, host_t *new_dst, + host_diff_t src_changes, host_diff_t dst_changes) { unsigned char request[BUFFER_SIZE]; struct nlmsghdr *hdr, *out = NULL; @@ -2277,9 +2285,8 @@ static void destroy(private_kernel_interface_t *this) close(this->socket_xfrm); close(this->socket_rt_events); close(this->socket_rt); - this->vips->destroy(this->vips); 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); } @@ -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.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.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; /* private members */ - this->vips = linked_list_create(); this->policies = linked_list_create(); - this->interfaces = linked_list_create(); + this->ifaces = linked_list_create(); this->hiter = NULL; this->seq = 200; 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"); } - /* 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); if (this->socket_rt_events <= 0) { 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))) { charon->kill(charon, "unable to bind RT event socket"); diff --git a/src/charon/kernel/kernel_interface.h b/src/charon/kernel/kernel_interface.h index 39eb6d475..62acb45bd 100644 --- a/src/charon/kernel/kernel_interface.h +++ b/src/charon/kernel/kernel_interface.h @@ -325,13 +325,11 @@ struct kernel_interface_t { * * @param this calling object * @param virtual_ip virtual ip address to assign - * @param iface_ip IP of an interface to remove virtual IP from * @return * - SUCCESS * - FAILED if kernel comm failed */ - status_t (*del_ip) (kernel_interface_t *this, host_t *virtual_ip, - host_t *iface_ip); + status_t (*del_ip) (kernel_interface_t *this, host_t *virtual_ip); /** * @brief Destroys a kernel_interface object. diff --git a/src/charon/processing/jobs/roam_job.c b/src/charon/processing/jobs/roam_job.c new file mode 100644 index 000000000..c5acad60c --- /dev/null +++ b/src/charon/processing/jobs/roam_job.c @@ -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 . + * + * 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 + +#include "roam_job.h" + +#include +#include + + +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; +} + diff --git a/src/charon/processing/jobs/roam_job.h b/src/charon/processing/jobs/roam_job.h new file mode 100644 index 000000000..23d374ccb --- /dev/null +++ b/src/charon/processing/jobs/roam_job.h @@ -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 . + * + * 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 +#include +#include + +/** + * @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_*/ + diff --git a/src/charon/processing/jobs/send_dpd_job.c b/src/charon/processing/jobs/send_dpd_job.c index cb259d9c6..f6786bfb4 100644 --- a/src/charon/processing/jobs/send_dpd_job.c +++ b/src/charon/processing/jobs/send_dpd_job.c @@ -88,9 +88,7 @@ send_dpd_job_t *send_dpd_job_create(ike_sa_id_t *ike_sa_id) /* interface functions */ this->public.job_interface.destroy = (void (*) (job_t *)) destroy; this->public.job_interface.execute = (void (*) (job_t *)) execute; - - /* public functions */ - this->public.destroy = (void (*)(send_dpd_job_t *)) destroy; + this->public.job_interface.destroy = (void (*) (job_t *)) destroy; /* private variables */ this->ike_sa_id = ike_sa_id->clone(ike_sa_id); diff --git a/src/charon/processing/jobs/send_dpd_job.h b/src/charon/processing/jobs/send_dpd_job.h index 26c9e2e81..0e4059131 100644 --- a/src/charon/processing/jobs/send_dpd_job.h +++ b/src/charon/processing/jobs/send_dpd_job.h @@ -45,13 +45,6 @@ struct send_dpd_job_t { * implements job_t 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); }; /** diff --git a/src/charon/processing/jobs/send_keepalive_job.c b/src/charon/processing/jobs/send_keepalive_job.c index 6d529e1b3..8cb51e5dd 100644 --- a/src/charon/processing/jobs/send_keepalive_job.c +++ b/src/charon/processing/jobs/send_keepalive_job.c @@ -82,9 +82,7 @@ send_keepalive_job_t *send_keepalive_job_create(ike_sa_id_t *ike_sa_id) /* interface functions */ this->public.job_interface.destroy = (void (*) (job_t *)) destroy; this->public.job_interface.execute = (void (*) (job_t *)) execute; - - /* public functions */ - this->public.destroy = (void (*)(send_keepalive_job_t *)) destroy; + this->public.job_interface.destroy = (void (*) (job_t *)) destroy; /* private variables */ this->ike_sa_id = ike_sa_id->clone(ike_sa_id); diff --git a/src/charon/processing/jobs/send_keepalive_job.h b/src/charon/processing/jobs/send_keepalive_job.h index f7b38337e..e8d214aed 100644 --- a/src/charon/processing/jobs/send_keepalive_job.h +++ b/src/charon/processing/jobs/send_keepalive_job.h @@ -44,13 +44,6 @@ struct send_keepalive_job_t { * implements job_t 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); }; /** diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index a23bb4a07..00f95960a 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -148,6 +149,11 @@ struct private_ike_sa_t { * set of extensions the peer supports */ 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. @@ -194,16 +200,6 @@ struct private_ike_sa_t { */ 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 */ @@ -218,6 +214,11 @@ struct private_ike_sa_t { * List of DNS servers installed by us */ linked_list_t *dns_servers; + + /** + * list of peers additional addresses, transmitted via MOBIKE + */ + linked_list_t *additional_addresses; /** * 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); } - if (!this->nat_here) + if (!(this->conditions & COND_NAT_THERE)) { /* update without restrictions if we are not NATted */ 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); task = (task_t*)ike_config_create(&this->public, TRUE); 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); @@ -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); task = (task_t*)ike_config_create(&this->public, TRUE); 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); @@ -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); 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); } 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); 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); } 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) { - 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); } /** @@ -1588,6 +1664,84 @@ static status_t reestablish(private_ike_sa_t *this) 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. @@ -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); } -/** - * 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 */ @@ -1818,13 +1946,16 @@ static void destroy(private_ike_sa_t *this) if (this->my_virtual_ip) { 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); } DESTROY_IF(this->other_virtual_ip); 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->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.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.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.delete = (status_t (*)(ike_sa_t*))delete_; 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.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.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.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.generate_message = (status_t (*)(ike_sa_t*,message_t*,packet_t**))generate_message; 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_ca = NULL; this->extensions = 0; + this->conditions = 0; this->crypter_in = NULL; this->crypter_out = 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_build = chunk_empty; this->child_prf = NULL; - this->nat_here = FALSE; - this->nat_there = FALSE; this->state = IKE_CREATED; this->time.inbound = this->time.outbound = time(NULL); 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->other_virtual_ip = NULL; this->dns_servers = linked_list_create(); + this->additional_addresses = linked_list_create(); this->keyingtry = 0; return &this->public; diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h index 3905a89c7..f4ca5ae69 100644 --- a/src/charon/sa/ike_sa.h +++ b/src/charon/sa/ike_sa.h @@ -26,6 +26,7 @@ #define IKE_SA_H_ 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 struct ike_sa_t ike_sa_t; @@ -79,12 +80,38 @@ enum ike_extension_t { /** * peer supports NAT traversal as specified in RFC4306 */ - EXT_NATT, + EXT_NATT = (1<<0), /** * 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); /** - * @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 extension extension to check for support - * @return TRUE if peer supports it, FALSE otherwise + * @param host host to add to list */ - 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. @@ -355,6 +394,33 @@ struct ike_sa_t { */ 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. * @@ -424,6 +490,20 @@ struct ike_sa_t { */ 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. * @@ -493,29 +573,6 @@ struct ike_sa_t { * @param this calling object */ 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. diff --git a/src/charon/sa/task_manager.c b/src/charon/sa/task_manager.c index 11c2592ba..84ce1fb54 100644 --- a/src/charon/sa/task_manager.c +++ b/src/charon/sa/task_manager.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -130,6 +131,11 @@ struct private_task_manager_t { * List of tasks initiated by peer */ 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; this->queued_tasks->destroy_offset(this->queued_tasks, - offsetof(task_t, destroy)); + offsetof(task_t, destroy)); this->passive_tasks->destroy_offset(this->passive_tasks, 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_CONFIG); activate_task(this, CHILD_CREATE); + activate_task(this, IKE_MOBIKE); } break; case IKE_ESTABLISHED: @@ -307,7 +314,7 @@ static status_t build_request(private_task_manager_t *this) exchange = INFORMATIONAL; break; } - if (activate_task(this, IKE_DEADPEER)) + if (activate_task(this, IKE_DPD)) { exchange = INFORMATIONAL; break; @@ -420,6 +427,8 @@ static status_t process_response(private_task_manager_t *this, return DESTROY_ME; } + /* catch if we get resetted while processing */ + this->reset = FALSE; iterator = this->active_tasks->create_iterator(this->active_tasks, TRUE); while (iterator->iterate(iterator, (void*)&task)) { @@ -439,6 +448,12 @@ static status_t process_response(private_task_manager_t *this, iterator->destroy(iterator); 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); @@ -597,6 +612,8 @@ static status_t process_request(private_task_manager_t *this, this->passive_tasks->insert_last(this->passive_tasks, task); task = (task_t*)child_create_create(this->ike_sa, NULL); 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; } case CREATE_CHILD_SA: @@ -812,7 +829,7 @@ static void reset(private_task_manager_t *this) this->responding.packet = NULL; this->initiating.packet = NULL; this->responding.mid = 0; - this->initiating.mid = -1; + this->initiating.mid = 0; this->initiating.type = EXCHANGE_TYPE_UNDEFINED; /* reset active tasks */ @@ -822,6 +839,8 @@ static void reset(private_task_manager_t *this) task->migrate(task, this->ike_sa); 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->active_tasks = linked_list_create(); this->passive_tasks = linked_list_create(); + this->reset = FALSE; return &this->public; } diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c index f70730b05..7bf22130e 100644 --- a/src/charon/sa/tasks/child_create.c +++ b/src/charon/sa/tasks/child_create.c @@ -297,7 +297,7 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) this->mode = MODE_TUNNEL; 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; 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->mode = this->config->get_mode(this->config); - this->child_sa = child_sa_create(me, other, - this->ike_sa->get_my_id(this->ike_sa), - this->ike_sa->get_other_id(this->ike_sa), - this->config, this->reqid, - this->ike_sa->is_natt_enabled(this->ike_sa)); + this->child_sa = child_sa_create( + me, other, this->ike_sa->get_my_id(this->ike_sa), + this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid, + this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)); 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; } - this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa), - this->ike_sa->get_other_host(this->ike_sa), - this->ike_sa->get_my_id(this->ike_sa), - this->ike_sa->get_other_id(this->ike_sa), - this->config, this->reqid, - this->ike_sa->is_natt_enabled(this->ike_sa)); + this->child_sa = child_sa_create( + this->ike_sa->get_my_host(this->ike_sa), + this->ike_sa->get_other_host(this->ike_sa), + this->ike_sa->get_my_id(this->ike_sa), + this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid, + this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY)); switch (select_and_install(this, no_dh)) { diff --git a/src/charon/sa/tasks/ike_auth.c b/src/charon/sa/tasks/ike_auth.c index d0dd49aee..c1c0cd5a2 100644 --- a/src/charon/sa/tasks/ike_auth.c +++ b/src/charon/sa/tasks/ike_auth.c @@ -636,7 +636,12 @@ static status_t process_i(private_ike_auth_t *this, message_t *message) case INVALID_SELECTORS: /* these are errors, but are not critical as only the * 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: { if (type < 16383) diff --git a/src/charon/sa/tasks/ike_dpd.c b/src/charon/sa/tasks/ike_dpd.c index 1cb05c45c..be751766e 100644 --- a/src/charon/sa/tasks/ike_dpd.c +++ b/src/charon/sa/tasks/ike_dpd.c @@ -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) { - return IKE_DEADPEER; + return IKE_DPD; } /** diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c new file mode 100644 index 000000000..0b3bd072b --- /dev/null +++ b/src/charon/sa/tasks/ike_mobike.c @@ -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 . + * + * 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 + +#include +#include + + +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; +} + diff --git a/src/charon/sa/tasks/ike_mobike.h b/src/charon/sa/tasks/ike_mobike.h new file mode 100644 index 000000000..f815e4998 --- /dev/null +++ b/src/charon/sa/tasks/ike_mobike.h @@ -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 . + * + * 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 +#include +#include + +/** + * @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_ */ + diff --git a/src/charon/sa/tasks/ike_natd.c b/src/charon/sa/tasks/ike_natd.c index 15c516c67..db8a400cc 100644 --- a/src/charon/sa/tasks/ike_natd.c +++ b/src/charon/sa/tasks/ike_natd.c @@ -207,11 +207,11 @@ static void process_payloads(private_ike_natd_t *this, message_t *message) 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) { - 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); - 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; diff --git a/src/charon/sa/tasks/ike_reauth.c b/src/charon/sa/tasks/ike_reauth.c index 93be23dd3..0e98382a8 100644 --- a/src/charon/sa/tasks/ike_reauth.c +++ b/src/charon/sa/tasks/ike_reauth.c @@ -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)); host = this->ike_sa->get_other_host(this->ike_sa); 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 */ host = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE); if (host) diff --git a/src/charon/sa/tasks/task.c b/src/charon/sa/tasks/task.c index 68d8ebf0c..713403d47 100644 --- a/src/charon/sa/tasks/task.c +++ b/src/charon/sa/tasks/task.c @@ -25,14 +25,16 @@ ENUM(task_type_names, IKE_INIT, CHILD_REKEY, "IKE_INIT", "IKE_NATD", + "IKE_MOBIKE", "IKE_AUTHENTICATE", "IKE_CERT", "IKE_CONFIG", - "IKE_DPD", "IKE_REKEY", + "IKE_REAUTH", "IKE_DELETE", - "IKE_DEADPEER", + "IKE_DPD", "CHILD_CREATE", "CHILD_DELETE", "CHILD_REKEY", ); + diff --git a/src/charon/sa/tasks/task.h b/src/charon/sa/tasks/task.h index 2b45d264f..ff60ea816 100644 --- a/src/charon/sa/tasks/task.h +++ b/src/charon/sa/tasks/task.h @@ -40,14 +40,14 @@ enum task_type_t { IKE_INIT, /** detect NAT situation */ IKE_NATD, + /** handle MOBIKE stuff */ + IKE_MOBIKE, /** authenticate the initiated IKE_SA */ IKE_AUTHENTICATE, /** exchange certificates and requests */ IKE_CERT, /** Configuration payloads, virtual IP and such */ IKE_CONFIG, - /** DPD detection */ - IKE_DEADPEER, /** rekey an IKE_SA */ IKE_REKEY, /** reestablish a complete IKE_SA */