diff options
author | Martin Willi <martin@strongswan.org> | 2006-05-31 14:23:15 +0000 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2006-05-31 14:23:15 +0000 |
commit | 32b6500fbfe063f3efb5589facd027f4c6cf08ed (patch) | |
tree | c434114b344ff3a134ebf245a6865ff2794da590 /src/charon/threads/kernel_interface.c | |
parent | 6f2aba1322ce0061c56b9faeb979c236da926c3f (diff) | |
download | strongswan-32b6500fbfe063f3efb5589facd027f4c6cf08ed.tar.bz2 strongswan-32b6500fbfe063f3efb5589facd027f4c6cf08ed.tar.xz |
job management:
moved job code from thread_pool to job, jobs have an "execute" method now
added two new jobs: delete_child_sa & rekey_child_sa
kernel interface:
listens now for ACQUIRE & EXPIRE
supports hard and soft lifetimes
fires jobs for delete and rekey child sa
ike sa manager:
can checkout IKE SAs by requid of owned CHILD SAs
we have now the infrastructure to do the rekeying... :-)
Diffstat (limited to 'src/charon/threads/kernel_interface.c')
-rw-r--r-- | src/charon/threads/kernel_interface.c | 82 |
1 files changed, 70 insertions, 12 deletions
diff --git a/src/charon/threads/kernel_interface.c b/src/charon/threads/kernel_interface.c index 679cf69ee..d88fa3f29 100644 --- a/src/charon/threads/kernel_interface.c +++ b/src/charon/threads/kernel_interface.c @@ -36,6 +36,8 @@ #include <daemon.h> #include <utils/linked_list.h> +#include <queues/jobs/delete_child_sa_job.h> +#include <queues/jobs/rekey_child_sa_job.h> #define KERNEL_ESP 50 @@ -101,6 +103,8 @@ struct netlink_message_t { struct xfrm_userpolicy_id policy_id; /** message for policy installation */ struct xfrm_userpolicy_info policy; + /** expire message sent from kernel */ + struct xfrm_user_expire expire; }; u_int8_t data[XFRM_DATA_LENGTH]; }; @@ -205,7 +209,6 @@ mapping_t kernel_integrity_algs_m[] = { {MAPPING_END, NULL} }; - /** * Implementation of kernel_interface_t.get_spi. */ @@ -272,6 +275,8 @@ static status_t add_sa( private_kernel_interface_t *this, u_int32_t spi, int protocol, u_int32_t reqid, + u_int64_t expire_soft, + u_int64_t expire_hard, encryption_algorithm_t enc_alg, chunk_t encryption_key, integrity_algorithm_t int_alg, @@ -296,10 +301,16 @@ static status_t add_sa( private_kernel_interface_t *this, request.sa.mode = TRUE; /* tunnel mode */ request.sa.replay_window = 32; request.sa.reqid = reqid; + /* we currently do not expire SAs by volume/packet count */ request.sa.lft.soft_byte_limit = XFRM_INF; - request.sa.lft.soft_packet_limit = XFRM_INF; request.sa.lft.hard_byte_limit = XFRM_INF; + request.sa.lft.soft_packet_limit = XFRM_INF; request.sa.lft.hard_packet_limit = XFRM_INF; + /* we use lifetimes since added, not since used */ + request.sa.lft.soft_add_expires_seconds = expire_soft; + request.sa.lft.hard_add_expires_seconds = expire_hard; + request.sa.lft.soft_use_expires_seconds = 0; + request.sa.lft.hard_use_expires_seconds = 0; request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.sa))); @@ -435,10 +446,15 @@ static status_t add_policy(private_kernel_interface_t *this, request.policy.action = XFRM_POLICY_ALLOW; request.policy.share = XFRM_SHARE_ANY; + /* policies currently don't expire */ request.policy.lft.soft_byte_limit = XFRM_INF; 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.sa.lft.soft_add_expires_seconds = 0; + request.sa.lft.hard_add_expires_seconds = 0; + request.sa.lft.soft_use_expires_seconds = 0; + request.sa.lft.hard_use_expires_seconds = 0; if (esp || ah) { @@ -645,30 +661,58 @@ static void receive_messages(private_kernel_interface_t *this) /* not from kernel. not interested, try another one */ continue; } + /* good message, handle it */ break; } - /* got a valid message. - * requests are handled on our own, - * responses are listed for the requesters + /* we handle ACQUIRE and EXPIRE messages directly */ - if (response.hdr.nlmsg_flags & NLM_F_REQUEST) + if (response.hdr.nlmsg_type == XFRM_MSG_ACQUIRE) + { + this->logger->log(this->logger, CONTROL, + "Received a XFRM_MSG_ACQUIRE. Ignored"); + } + else if (response.hdr.nlmsg_type == XFRM_MSG_EXPIRE) { - /* handle request */ + job_t *job; + this->logger->log(this->logger, CONTROL|LEVEL1, + "Received a XFRM_MSG_EXPIRE"); + this->logger->log(this->logger, CONTROL|LEVEL0, + "creating %s job for CHILD_SA with reqid %d", + response.expire.hard ? "delete" : "rekey", + response.expire.state.reqid); + if (response.expire.hard) + { + job = (job_t*)delete_child_sa_job_create( + response.expire.state.reqid); + } + else + { + job = (job_t*)rekey_child_sa_job_create( + response.expire.state.reqid); + } + charon->job_queue->add(charon->job_queue, job); } - else + /* NLMSG_ERROR is send back for acknowledge (or on error), an + * XFRM_MSG_NEWSA is returned when we alloc spis. + * list these responses for the sender + */ + else if (response.hdr.nlmsg_type == NLMSG_ERROR || + response.hdr.nlmsg_type == XFRM_MSG_NEWSA) { - /* add response to queue */ + /* add response to queue */ listed_response = malloc(sizeof(response)); memcpy(listed_response, &response, sizeof(response)); - + pthread_mutex_lock(&(this->mutex)); this->responses->insert_last(this->responses, (void*)listed_response); pthread_mutex_unlock(&(this->mutex)); /* signal ALL waiting threads */ pthread_cond_broadcast(&(this->condvar)); } - /* get the next one */ + /* we are not interested in anything other. + * anyway, move on to the next message */ + continue; } } @@ -689,11 +733,12 @@ static void destroy(private_kernel_interface_t *this) */ kernel_interface_t *kernel_interface_create() { + struct sockaddr_nl addr; private_kernel_interface_t *this = malloc_thing(private_kernel_interface_t); /* public functions */ 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_sa = (status_t(*)(kernel_interface_t *,host_t*,host_t*,u_int32_t,protocol_id_t,u_int32_t,u_int64_t,u_int64_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; this->public.del_sa = (status_t(*)(kernel_interface_t*,host_t*,u_int32_t,protocol_id_t))del_sa; this->public.del_policy = (status_t(*)(kernel_interface_t*,host_t*,host_t*,host_t*,host_t*,u_int8_t,u_int8_t,int,int))del_policy; @@ -709,6 +754,8 @@ kernel_interface_t *kernel_interface_create() pthread_mutex_init(&(this->mutex),NULL); pthread_cond_init(&(this->condvar),NULL); this->seq = 0; + + /* open netlink socket */ this->socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_XFRM); if (this->socket <= 0) { @@ -716,6 +763,17 @@ kernel_interface_t *kernel_interface_create() free(this); charon->kill(charon, "Unable to create netlink socket"); } + /* bind the socket and reqister for ACQUIRE & EXPIRE */ + addr.nl_family = AF_NETLINK; + addr.nl_pid = getpid(); + addr.nl_groups = XFRMGRP_ACQUIRE | XFRMGRP_EXPIRE; + if (bind(this->socket, (struct sockaddr*)&addr, sizeof(addr)) != 0) + { + this->responses->destroy(this->responses); + close(this->socket); + free(this); + charon->kill(charon, "Unable to bind netlink socket"); + } if (pthread_create(&(this->thread), NULL, (void*(*)(void*))this->receive_messages, this) != 0) { |