diff options
Diffstat (limited to 'Source/charon')
-rw-r--r-- | Source/charon/config/configuration_manager.c | 11 | ||||
-rw-r--r-- | Source/charon/daemon.c | 8 | ||||
-rw-r--r-- | Source/charon/sa/child_sa.c | 287 | ||||
-rw-r--r-- | Source/charon/sa/child_sa.h | 2 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_auth_requested.c | 7 | ||||
-rw-r--r-- | Source/charon/sa/states/ike_sa_init_responded.c | 5 | ||||
-rw-r--r-- | Source/charon/threads/kernel_interface.c | 111 | ||||
-rw-r--r-- | Source/charon/threads/kernel_interface.h | 11 |
8 files changed, 343 insertions, 99 deletions
diff --git a/Source/charon/config/configuration_manager.c b/Source/charon/config/configuration_manager.c index c5c6ec6ae..7179e5555 100644 --- a/Source/charon/config/configuration_manager.c +++ b/Source/charon/config/configuration_manager.c @@ -311,16 +311,25 @@ static void load_default_config (private_configuration_manager_t *this) RSA_DIGITAL_SIGNATURE, 30000); - /* traffic selectors */ + /* traffic selectors alice */ ts = traffic_selector_create_from_string(1, TS_IPV4_ADDR_RANGE, "10.1.0.0", 0, "10.1.255.255", 65535); sa_config_a->add_my_traffic_selector(sa_config_a,ts); ts = traffic_selector_create_from_string(1, TS_IPV4_ADDR_RANGE, "10.2.0.0", 0, "10.2.255.255", 65535); sa_config_a->add_other_traffic_selector(sa_config_a,ts); + ts = traffic_selector_create_from_string(6, TS_IPV4_ADDR_RANGE, "10.1.0.0", 0, "10.1.255.255", 65535); + sa_config_a->add_my_traffic_selector(sa_config_a,ts); + ts = traffic_selector_create_from_string(6, TS_IPV4_ADDR_RANGE, "10.2.0.1", 22, "10.2.0.1", 22); + sa_config_a->add_other_traffic_selector(sa_config_a,ts); + /* traffic selectors bob */ ts = traffic_selector_create_from_string(1, TS_IPV4_ADDR_RANGE, "10.2.0.0", 0, "10.2.255.255", 65535); sa_config_b->add_my_traffic_selector(sa_config_b,ts); ts = traffic_selector_create_from_string(1, TS_IPV4_ADDR_RANGE, "10.1.0.0", 0, "10.1.255.255", 65535); sa_config_b->add_other_traffic_selector(sa_config_b,ts); + ts = traffic_selector_create_from_string(6, TS_IPV4_ADDR_RANGE, "10.2.0.0", 0, "10.2.255.255", 65535); + sa_config_b->add_my_traffic_selector(sa_config_b,ts); + ts = traffic_selector_create_from_string(6, TS_IPV4_ADDR_RANGE, "10.1.0.0", 0, "10.1.255.255", 65535); + sa_config_b->add_other_traffic_selector(sa_config_b,ts); /* child proposal for alice */ proposal = proposal_create(1); diff --git a/Source/charon/daemon.c b/Source/charon/daemon.c index 8e5f5e4bb..21ed44ef8 100644 --- a/Source/charon/daemon.c +++ b/Source/charon/daemon.c @@ -196,6 +196,10 @@ static void initialize(private_daemon_t *this) */ static void destroy(private_daemon_t *this) { + if (this->public.ike_sa_manager != NULL) + { + this->public.ike_sa_manager->destroy(this->public.ike_sa_manager); + } if (this->public.kernel_interface != NULL) { this->public.kernel_interface->destroy(this->public.kernel_interface); @@ -232,10 +236,6 @@ static void destroy(private_daemon_t *this) { this->public.socket->destroy(this->public.socket); } - if (this->public.ike_sa_manager != NULL) - { - this->public.ike_sa_manager->destroy(this->public.ike_sa_manager); - } if (this->public.configuration_manager != NULL) { this->public.configuration_manager->destroy(this->public.configuration_manager); diff --git a/Source/charon/sa/child_sa.c b/Source/charon/sa/child_sa.c index 2808cff7f..faadf27ce 100644 --- a/Source/charon/sa/child_sa.c +++ b/Source/charon/sa/child_sa.c @@ -27,6 +27,41 @@ #include <daemon.h> +typedef struct policy_t policy_t; + +/** + * Struct used to store information for a policy. This + * is needed since we must provide all this information + * for deleting a policy... + */ +struct policy_t { + + /** + * Network on local side + */ + host_t *my_net; + + /** + * Network on remote side + */ + host_t *other_net; + + /** + * Number of bits for local network (subnet size) + */ + u_int8_t my_net_mask; + + /** + * Number of bits for remote network (subnet size) + */ + u_int8_t other_net_mask; + + /** + * Protocol for this policy, such as TCP/UDP/ICMP... + */ + int upper_proto; +}; + typedef struct private_child_sa_t private_child_sa_t; /** @@ -49,14 +84,29 @@ struct private_child_sa_t { host_t *other; /** - * Security parameter index for AH protocol, 0 if not used + * Local security parameter index for AH protocol, 0 if not used + */ + u_int32_t my_ah_spi; + + /** + * Local security parameter index for ESP protocol, 0 if not used */ - u_int32_t ah_spi; + u_int32_t my_esp_spi; /** - * Security parameter index for ESP protocol, 0 if not used + * Remote security parameter index for AH protocol, 0 if not used */ - u_int32_t esp_spi; + u_int32_t other_ah_spi; + + /** + * Remote security parameter index for ESP protocol, 0 if not used + */ + u_int32_t other_esp_spi; + + /** + * List containing policy_id_t objects + */ + linked_list_t *policies; /** * reqid used for this child_sa @@ -94,31 +144,31 @@ static status_t alloc(private_child_sa_t *this, linked_list_t *proposals) { case AH: /* do we already have an spi for AH?*/ - if (this->ah_spi == 0) + if (this->my_ah_spi == 0) { /* nope, get one */ status = charon->kernel_interface->get_spi( charon->kernel_interface, this->me, this->other, AH, FALSE, - &(this->ah_spi)); + &(this->my_ah_spi)); } /* update proposal */ - proposal->set_spi(proposal, AH, (u_int64_t)this->ah_spi); + proposal->set_spi(proposal, AH, (u_int64_t)this->my_ah_spi); break; case ESP: /* do we already have an spi for ESP?*/ - if (this->esp_spi == 0) + if (this->my_esp_spi == 0) { /* nope, get one */ status = charon->kernel_interface->get_spi( charon->kernel_interface, this->me, this->other, ESP, FALSE, - &(this->esp_spi)); + &(this->my_esp_spi)); } /* update proposal */ - proposal->set_spi(proposal, ESP, (u_int64_t)this->esp_spi); + proposal->set_spi(proposal, ESP, (u_int64_t)this->my_esp_spi); break; default: break; @@ -175,16 +225,24 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal, prf_plus { if (protocols[i] == AH) { - spi = this->ah_spi; + spi = this->my_ah_spi; } else { - spi = this->esp_spi; + spi = this->my_esp_spi; } } else /* use proposals spi */ { spi = proposal->get_spi(proposal, protocols[i]); + if (protocols[i] == AH) + { + this->other_ah_spi = spi; + } + else + { + this->other_esp_spi = spi; + } } /* derive encryption key first */ @@ -336,72 +394,102 @@ static u_int8_t get_mask(chunk_t start, chunk_t end) return start.len * 8; } -static status_t add_policy(private_child_sa_t *this, linked_list_t *my_ts, linked_list_t *other_ts) +static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list, linked_list_t *other_ts_list) { - traffic_selector_t *local_ts, *remote_ts; - host_t *my_net, *other_net; - u_int8_t my_mask, other_mask; - int family; - chunk_t from_addr, to_addr; - u_int16_t from_port, to_port; - status_t status; - - my_ts->get_first(my_ts, (void**)&local_ts); - other_ts->get_first(other_ts, (void**)&remote_ts); - - family = local_ts->get_type(local_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6; - from_addr = local_ts->get_from_address(local_ts); - to_addr = local_ts->get_to_address(local_ts); - from_port = local_ts->get_from_port(local_ts); - to_port = local_ts->get_to_port(local_ts); - if (from_port != to_port) - { - from_port = 0; - } - my_net = host_create_from_chunk(family, from_addr, from_port); - my_mask = get_mask(from_addr, to_addr); - allocator_free_chunk(&from_addr); - allocator_free_chunk(&to_addr); + iterator_t *my_iter, *other_iter; + traffic_selector_t *my_ts, *other_ts; - family = remote_ts->get_type(remote_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6; - from_addr = remote_ts->get_from_address(remote_ts); - to_addr = remote_ts->get_to_address(remote_ts); - from_port = remote_ts->get_from_port(remote_ts); - to_port = remote_ts->get_to_port(remote_ts); - if (from_port != to_port) + /* iterate over both lists */ + my_iter = my_ts_list->create_iterator(my_ts_list, TRUE); + other_iter = other_ts_list->create_iterator(other_ts_list, TRUE); + while (my_iter->has_next(my_iter)) { - from_port = 0; - } - other_net = host_create_from_chunk(family, from_addr, from_port); - other_mask = get_mask(from_addr, to_addr); - allocator_free_chunk(&from_addr); - allocator_free_chunk(&to_addr); - - status = charon->kernel_interface->add_policy(charon->kernel_interface, - this->me, this->other, - my_net, other_net, - my_mask, other_mask, - XFRM_POLICY_OUT, - 0, this->ah_spi, this->esp_spi, - this->reqid); + my_iter->current(my_iter, (void**)&my_ts); + other_iter->reset(other_iter); + while (other_iter->has_next(other_iter)) + { + /* set up policies for every entry in my_ts_list to every entry in other_ts_list */ + int family; + chunk_t from_addr, to_addr; + u_int16_t from_port, to_port; + policy_t *policy; + status_t status; + + other_iter->current(other_iter, (void**)&other_ts); + + /* only set up policies if protocol matches */ + if (my_ts->get_protocol(my_ts) != other_ts->get_protocol(other_ts)) + { + continue; + } + policy = allocator_alloc_thing(policy_t); + policy->upper_proto = my_ts->get_protocol(my_ts); + + /* calculate net and ports for local side */ + family = my_ts->get_type(my_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6; + from_addr = my_ts->get_from_address(my_ts); + to_addr = my_ts->get_to_address(my_ts); + from_port = my_ts->get_from_port(my_ts); + to_port = my_ts->get_to_port(my_ts); + from_port = (from_port != to_port) ? 0 : from_port; + policy->my_net = host_create_from_chunk(family, from_addr, from_port); + policy->my_net_mask = get_mask(from_addr, to_addr); + allocator_free_chunk(&from_addr); + allocator_free_chunk(&to_addr); + + /* calculate net and ports for remote side */ + family = other_ts->get_type(other_ts) == TS_IPV4_ADDR_RANGE ? AF_INET : AF_INET6; + from_addr = other_ts->get_from_address(other_ts); + to_addr = other_ts->get_to_address(other_ts); + from_port = other_ts->get_from_port(other_ts); + to_port = other_ts->get_to_port(other_ts); + from_port = (from_port != to_port) ? 0 : from_port; + policy->other_net = host_create_from_chunk(family, from_addr, from_port); + policy->other_net_mask = get_mask(from_addr, to_addr); + allocator_free_chunk(&from_addr); + allocator_free_chunk(&to_addr); - status |= charon->kernel_interface->add_policy(charon->kernel_interface, - this->other, this->me, - other_net, my_net, - other_mask, my_mask, - XFRM_POLICY_IN, - 0, this->ah_spi, this->esp_spi, - this->reqid); + /* install 3 policies: out, in and forward */ + status = charon->kernel_interface->add_policy(charon->kernel_interface, + this->me, this->other, + policy->my_net, policy->other_net, + policy->my_net_mask, policy->other_net_mask, + XFRM_POLICY_OUT, policy->upper_proto, + this->my_ah_spi, this->my_esp_spi, + this->reqid); - status |= charon->kernel_interface->add_policy(charon->kernel_interface, - this->other, this->me, - other_net, my_net, - other_mask, my_mask, - XFRM_POLICY_FWD, - 0, this->ah_spi, this->esp_spi, - this->reqid); + status |= charon->kernel_interface->add_policy(charon->kernel_interface, + this->other, this->me, + policy->other_net, policy->my_net, + policy->other_net_mask, policy->my_net_mask, + XFRM_POLICY_IN, policy->upper_proto, + this->my_ah_spi, this->my_esp_spi, + this->reqid); - return status; + status |= charon->kernel_interface->add_policy(charon->kernel_interface, + this->other, this->me, + policy->other_net, policy->my_net, + policy->other_net_mask, policy->my_net_mask, + XFRM_POLICY_FWD, policy->upper_proto, + this->my_ah_spi, this->my_esp_spi, + this->reqid); + + if (status != SUCCESS) + { + my_iter->destroy(my_iter); + other_iter->destroy(other_iter); + allocator_free(policy); + return status; + } + + /* add it to the policy list, since we want to know which policies we own */ + this->policies->insert_last(this->policies, policy); + } + } + + my_iter->destroy(my_iter); + other_iter->destroy(other_iter); + return SUCCESS; } /** @@ -409,6 +497,50 @@ static status_t add_policy(private_child_sa_t *this, linked_list_t *my_ts, linke */ static void destroy(private_child_sa_t *this) { + /* delete all policys in the kernel */ + policy_t *policy; + while (this->policies->remove_last(this->policies, (void**)&policy) == SUCCESS) + { + charon->kernel_interface->del_policy(charon->kernel_interface, + this->me, this->other, + policy->my_net, policy->other_net, + policy->my_net_mask, policy->other_net_mask, + XFRM_POLICY_OUT, policy->upper_proto); + + charon->kernel_interface->del_policy(charon->kernel_interface, + this->other, this->me, + policy->other_net, policy->my_net, + policy->other_net_mask, policy->my_net_mask, + XFRM_POLICY_IN, policy->upper_proto); + + charon->kernel_interface->del_policy(charon->kernel_interface, + this->other, this->me, + policy->other_net, policy->my_net, + policy->other_net_mask, policy->my_net_mask, + XFRM_POLICY_FWD, policy->upper_proto); + + policy->my_net->destroy(policy->my_net); + policy->other_net->destroy(policy->other_net); + allocator_free(policy); + } + this->policies->destroy(this->policies); + + /* delete SAs in the kernel, if they are set up */ + if (this->my_ah_spi) + { + charon->kernel_interface->del_sa(charon->kernel_interface, + this->other, this->my_ah_spi, AH); + charon->kernel_interface->del_sa(charon->kernel_interface, + this->me, this->other_ah_spi, AH); + } + if (this->my_esp_spi) + { + charon->kernel_interface->del_sa(charon->kernel_interface, + this->other, this->my_esp_spi, ESP); + charon->kernel_interface->del_sa(charon->kernel_interface, + this->me, this->other_esp_spi, ESP); + } + charon->logger_manager->destroy_logger(charon->logger_manager, this->logger); allocator_free(this); } @@ -418,23 +550,26 @@ static void destroy(private_child_sa_t *this) */ child_sa_t * child_sa_create(host_t *me, host_t* other) { - static u_int32_t reqid = 123; + static u_int32_t reqid = 1; private_child_sa_t *this = allocator_alloc_thing(private_child_sa_t); /* public functions */ this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc; this->public.add = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))add; this->public.update = (status_t(*)(child_sa_t*,proposal_t*,prf_plus_t*))update; - this->public.add_policy = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policy; + this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*))add_policies; this->public.destroy = (void(*)(child_sa_t*))destroy; /* private data */ this->logger = charon->logger_manager->create_logger(charon->logger_manager, CHILD_SA, NULL); this->me = me; this->other = other; - this->ah_spi = 0; - this->esp_spi = 0; + this->my_ah_spi = 0; + this->my_esp_spi = 0; + this->other_ah_spi = 0; + this->other_esp_spi = 0; this->reqid = reqid++; + this->policies = linked_list_create(); return (&this->public); } diff --git a/Source/charon/sa/child_sa.h b/Source/charon/sa/child_sa.h index 4316f262a..bd48c603c 100644 --- a/Source/charon/sa/child_sa.h +++ b/Source/charon/sa/child_sa.h @@ -107,7 +107,7 @@ struct child_sa_t { * @param other_ts traffic selectors for remote site * @return SUCCESS or FAILED */ - status_t (*add_policy) (child_sa_t *this, linked_list_t *my_ts, linked_list_t *other_ts); + status_t (*add_policies) (child_sa_t *this, linked_list_t *my_ts_list, linked_list_t *other_ts_list); /** * @brief Destroys a child_sa. diff --git a/Source/charon/sa/states/ike_auth_requested.c b/Source/charon/sa/states/ike_auth_requested.c index 35e4c24ff..ed5360dfe 100644 --- a/Source/charon/sa/states/ike_auth_requested.c +++ b/Source/charon/sa/states/ike_auth_requested.c @@ -317,10 +317,14 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i if (!this->proposal) { this->logger->log(this->logger, CONTROL, "Proposal negotiation failed, no CHILD_SA built"); + this->child_sa->destroy(this->child_sa); + this->child_sa = NULL; } else if (this->my_ts->get_count(this->my_ts) == 0 || this->other_ts->get_count(this->other_ts) == 0) { this->logger->log(this->logger, CONTROL, "Traffic selector negotiation failed, no CHILD_SA built"); + this->child_sa->destroy(this->child_sa); + this->child_sa = NULL; } else { @@ -337,7 +341,7 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA! Deleting IKE_SA"); return DELETE_ME; } - status = this->child_sa->add_policy(this->child_sa, this->my_ts, this->other_ts); + status = this->child_sa->add_policies(this->child_sa, this->my_ts, this->other_ts); if (status != SUCCESS) { this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA policy! Deleting IKE_SA"); @@ -354,7 +358,6 @@ static status_t process_message(private_ike_auth_requested_t *this, message_t *i my_host->get_address(my_host), other_host->get_address(other_host), mapping_find(auth_method_m, auth_payload->get_auth_method(auth_payload))); - this->ike_sa->create_delete_established_ike_sa_job(this->ike_sa,this->sa_config->get_ike_sa_lifetime(this->sa_config)); this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa)); this->destroy_after_state_change(this); return SUCCESS; diff --git a/Source/charon/sa/states/ike_sa_init_responded.c b/Source/charon/sa/states/ike_sa_init_responded.c index da0b0a7f6..379eaebe1 100644 --- a/Source/charon/sa/states/ike_sa_init_responded.c +++ b/Source/charon/sa/states/ike_sa_init_responded.c @@ -346,10 +346,12 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t else if (this->my_ts->get_count(this->my_ts) == 0 || this->other_ts->get_count(this->other_ts) == 0) { this->logger->log(this->logger, CONTROL, "Traffic selector negotiation failed, no CHILD_SA built"); + this->child_sa->destroy(this->child_sa); + this->child_sa = NULL; } else { - status = this->child_sa->add_policy(this->child_sa, this->my_ts, this->other_ts); + status = this->child_sa->add_policies(this->child_sa, this->my_ts, this->other_ts); if (status != SUCCESS) { this->logger->log(this->logger, AUDIT, "Could not install CHILD_SA policy! Deleting IKE_SA"); @@ -365,7 +367,6 @@ static status_t process_message(private_ike_sa_init_responded_t *this, message_t my_host->get_address(my_host), other_host->get_address(other_host), mapping_find(auth_method_m, auth_request->get_auth_method(auth_request))); - this->ike_sa->create_delete_established_ike_sa_job(this->ike_sa,this->sa_config->get_ike_sa_lifetime(this->sa_config)); this->ike_sa->set_new_state(this->ike_sa, (state_t*)ike_sa_established_create(this->ike_sa)); this->destroy_after_state_change(this); diff --git a/Source/charon/threads/kernel_interface.c b/Source/charon/threads/kernel_interface.c index efb058c29..8ff1affbd 100644 --- a/Source/charon/threads/kernel_interface.c +++ b/Source/charon/threads/kernel_interface.c @@ -88,16 +88,14 @@ struct netlink_message_t { struct nlmsgerr e; /* message for spi allocation */ struct xfrm_userspi_info spi; + /* message for SA manipulation */ + struct xfrm_usersa_id sa_id; /* message for SA installation */ - struct { - struct xfrm_usersa_info sa; - }; + struct xfrm_usersa_info sa; /* message for policy manipulation */ - struct xfrm_userpolicy_id id; + struct xfrm_userpolicy_id policy_id; /* message for policy installation */ - struct { - struct xfrm_userpolicy_info policy; - }; + struct xfrm_userpolicy_info policy; }; u_int8_t data[512]; }; @@ -308,6 +306,43 @@ static status_t add_sa( private_kernel_interface_t *this, return SUCCESS; } +static status_t del_sa( private_kernel_interface_t *this, + host_t *dst, + u_int32_t spi, + protocol_id_t protocol) +{ + netlink_message_t request, *response; + memset(&request, 0, sizeof(request)); + status_t status; + + request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + request.hdr.nlmsg_type = XFRM_MSG_DELSA; + + request.sa_id.daddr = dst->get_xfrm_addr(dst); + + request.sa_id.spi = spi; + request.sa_id.proto = (protocol == ESP) ? KERNEL_ESP : KERNEL_AH; + request.sa_id.family = dst->get_family(dst); + + request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.sa_id))); + + if (this->send_message(this, &request, &response) != SUCCESS) + { + status = FAILED; + } + else if (response->hdr.nlmsg_type != NLMSG_ERROR) + { + status = FAILED; + } + else if (response->e.error) + { + status = FAILED; + } + + allocator_free(response); + return SUCCESS; +} + static status_t add_policy(private_kernel_interface_t *this, host_t *me, host_t *other, host_t *src, host_t *dst, @@ -332,7 +367,10 @@ static status_t add_policy(private_kernel_interface_t *this, request.policy.sel.prefixlen_d = dst_hostbits; request.policy.sel.proto = upper_proto; request.policy.sel.family = src->get_family(src); - + + request.hdr.nlmsg_type = XFRM_MSG_NEWPOLICY; + request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.policy))); + request.policy.dir = direction; request.policy.priority = SPD_PRIORITY; request.policy.action = XFRM_POLICY_ALLOW; @@ -342,9 +380,6 @@ static status_t add_policy(private_kernel_interface_t *this, request.policy.lft.soft_packet_limit = XFRM_INF; request.policy.lft.hard_byte_limit = XFRM_INF; request.policy.lft.hard_packet_limit = XFRM_INF; - - request.hdr.nlmsg_type = XFRM_MSG_NEWPOLICY; - request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.policy))); if (esp || ah) { @@ -358,7 +393,7 @@ static status_t add_policy(private_kernel_interface_t *this, data->tmpl[tmpl_pos].id.proto = KERNEL_ESP; data->tmpl[tmpl_pos].aalgos = data->tmpl[tmpl_pos].ealgos = data->tmpl[tmpl_pos].calgos = ~0; data->tmpl[tmpl_pos].mode = TRUE; - + data->tmpl[tmpl_pos].saddr = me->get_xfrm_addr(me); data->tmpl[tmpl_pos].id.daddr = me->get_xfrm_addr(other); @@ -370,7 +405,7 @@ static status_t add_policy(private_kernel_interface_t *this, data->tmpl[tmpl_pos].id.proto = KERNEL_AH; data->tmpl[tmpl_pos].aalgos = data->tmpl[tmpl_pos].ealgos = data->tmpl[tmpl_pos].calgos = ~0; data->tmpl[tmpl_pos].mode = TRUE; - + data->tmpl[tmpl_pos].saddr = me->get_xfrm_addr(me); data->tmpl[tmpl_pos].id.daddr = other->get_xfrm_addr(other); @@ -397,6 +432,51 @@ static status_t add_policy(private_kernel_interface_t *this, return status; } +static status_t del_policy(private_kernel_interface_t *this, + host_t *me, host_t *other, + host_t *src, host_t *dst, + u_int8_t src_hostbits, u_int8_t dst_hostbits, + int direction, int upper_proto) +{ + netlink_message_t request, *response; + status_t status = SUCCESS; + + memset(&request, 0, sizeof(request)); + request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + + request.policy_id.sel.sport = htons(src->get_port(src)); + request.policy_id.sel.dport = htons(dst->get_port(dst)); + request.policy_id.sel.sport_mask = (request.policy.sel.sport) ? ~0 : 0; + request.policy_id.sel.dport_mask = (request.policy.sel.dport) ? ~0 : 0; + request.policy_id.sel.saddr = src->get_xfrm_addr(src); + request.policy_id.sel.daddr = dst->get_xfrm_addr(dst); + request.policy_id.sel.prefixlen_s = src_hostbits; + request.policy_id.sel.prefixlen_d = dst_hostbits; + request.policy_id.sel.proto = upper_proto; + request.policy_id.sel.family = src->get_family(src); + + request.policy_id.dir = direction; + + request.hdr.nlmsg_type = XFRM_MSG_DELPOLICY; + request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.policy_id))); + + if (this->send_message(this, &request, &response) != SUCCESS) + { + status = FAILED; + } + else if (response->hdr.nlmsg_type != NLMSG_ERROR) + { + status = FAILED; + } + else if (response->e.error) + { + status = FAILED; + } + + allocator_free(response); + return status; +} + static status_t send_message(private_kernel_interface_t *this, netlink_message_t *request, netlink_message_t **response) { @@ -533,6 +613,8 @@ static void destroy(private_kernel_interface_t *this) allocator_free(this); } +#define ASSIGN(member, function) member = (void*)function + /* * Described in header. */ @@ -544,6 +626,9 @@ kernel_interface_t *kernel_interface_create() this->public.get_spi = (status_t(*)(kernel_interface_t*,host_t*,host_t*,protocol_id_t,u_int32_t,u_int32_t*))get_spi; this->public.add_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,encryption_algorithm_t,chunk_t,integrity_algorithm_t,chunk_t,bool))add_sa; this->public.add_policy = (status_t(*)(kernel_interface_t*,host_t*, host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int,bool,bool,u_int32_t))add_policy; + ASSIGN(this->public.del_sa, del_sa); + ASSIGN(this->public.del_policy, del_policy); + this->public.destroy = (void(*)(kernel_interface_t*)) destroy; /* private members */ diff --git a/Source/charon/threads/kernel_interface.h b/Source/charon/threads/kernel_interface.h index 17b636dd1..7c2a27147 100644 --- a/Source/charon/threads/kernel_interface.h +++ b/Source/charon/threads/kernel_interface.h @@ -69,6 +69,11 @@ struct kernel_interface_t { chunk_t integrity_key, bool replace); + status_t (*del_sa) (kernel_interface_t *this, + host_t *dst, + u_int32_t spi, + protocol_id_t protocol); + status_t (*add_policy) (kernel_interface_t *this, host_t *me, host_t *other, host_t *src, host_t *dst, @@ -77,6 +82,12 @@ struct kernel_interface_t { bool ah, bool esp, u_int32_t reqid); + status_t (*del_policy) (kernel_interface_t *this, + host_t *me, host_t *other, + host_t *src, host_t *dst, + u_int8_t src_hostbits, u_int8_t dst_hostbits, + int direction, int upper_proto); + /** * @brief Destroys a kernel_interface object. * |