diff options
Diffstat (limited to 'Source/charon/threads')
-rw-r--r-- | Source/charon/threads/kernel_interface.c | 276 | ||||
-rw-r--r-- | Source/charon/threads/kernel_interface.h | 4 |
2 files changed, 143 insertions, 137 deletions
diff --git a/Source/charon/threads/kernel_interface.c b/Source/charon/threads/kernel_interface.c index 4fba85cbd..f5273e100 100644 --- a/Source/charon/threads/kernel_interface.c +++ b/Source/charon/threads/kernel_interface.c @@ -40,6 +40,10 @@ #include <utils/linked_list.h> +#define KERNEL_ESP 50 +#define KERNEL_AH 51 + + typedef struct netlink_message_t netlink_message_t; /** @@ -83,48 +87,48 @@ struct private_kernel_interface_t { /** * Public part of the kernel_interface_t object. */ - kernel_interface_t public; - - /** - * Netlink communication socket. - */ - int socket; - + kernel_interface_t public; + + /** + * Netlink communication socket. + */ + int socket; + pid_t pid; - /** - * Sequence number for messages. - */ - u_int32_t seq; - - /** - * List of responded messages. - */ - linked_list_t *responses; - - /** - * Thread which receives messages. - */ - pthread_t thread; - - /** - * Mutex locks access to replies list. - */ - pthread_mutex_t mutex; - - /** - * Condvar allows signaling of threads waiting for a reply. - */ - pthread_cond_t condvar; - - /** - * Function for the thread, receives messages. - */ - void (*receive_messages) (private_kernel_interface_t *this); - - /** - * Sends a netlink_message_t down to the kernel and wait for reply. - */ - status_t (*send_message) (private_kernel_interface_t *this, netlink_message_t *request, netlink_message_t **response); + /** + * Sequence number for messages. + */ + u_int32_t seq; + + /** + * List of responded messages. + */ + linked_list_t *responses; + + /** + * Thread which receives messages. + */ + pthread_t thread; + + /** + * Mutex locks access to replies list. + */ + pthread_mutex_t mutex; + + /** + * Condvar allows signaling of threads waiting for a reply. + */ + pthread_cond_t condvar; + + /** + * Function for the thread, receives messages. + */ + void (*receive_messages) (private_kernel_interface_t *this); + + /** + * Sends a netlink_message_t down to the kernel and wait for reply. + */ + status_t (*send_message) (private_kernel_interface_t *this, netlink_message_t *request, netlink_message_t **response); }; mapping_t kernel_encryption_algs_m[] = { @@ -157,41 +161,42 @@ static status_t get_spi(private_kernel_interface_t *this, host_t *src, host_t *d { netlink_message_t request, *response; - memset(&request, 0, sizeof(request)); - request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.spi))); - request.hdr.nlmsg_flags = NLM_F_REQUEST; - request.hdr.nlmsg_type = XFRM_MSG_ALLOCSPI; + memset(&request, 0, sizeof(request)); + request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.spi))); + request.hdr.nlmsg_flags = NLM_F_REQUEST; + request.hdr.nlmsg_type = XFRM_MSG_ALLOCSPI; request.spi.info.saddr = src->get_xfrm_addr(src); request.spi.info.id.daddr = dest->get_xfrm_addr(dest); - request.spi.info.mode = tunnel_mode; - request.spi.info.id.proto = protocol; - request.spi.info.family = PF_INET; - request.spi.min = 100; - request.spi.max = 200; - - if (this->send_message(this, &request, &response) != SUCCESS) - { - return FAILED; - } - - if (response->hdr.nlmsg_type == NLMSG_ERROR) - { - return FAILED; - } - - if (response->hdr.nlmsg_type != XFRM_MSG_NEWSA) - { - return FAILED; - } - else if (response->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(response->sa))) - { + request.spi.info.mode = tunnel_mode; + /* TODO: this should be done with getprotobyname() */ + request.spi.info.id.proto = (protocol == ESP) ? KERNEL_ESP : KERNEL_AH; + request.spi.info.family = PF_INET; + request.spi.min = 100; + request.spi.max = 200; + + if (this->send_message(this, &request, &response) != SUCCESS) + { return FAILED; - } + } + + if (response->hdr.nlmsg_type == NLMSG_ERROR) + { + return FAILED; + } + + if (response->hdr.nlmsg_type != XFRM_MSG_NEWSA) + { + return FAILED; + } + else if (response->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(response->sa))) + { + return FAILED; + } *spi = response->sa.id.spi; allocator_free(response); - - return SUCCESS; + + return SUCCESS; } static status_t add_sa( private_kernel_interface_t *this, @@ -206,45 +211,46 @@ static status_t add_sa( private_kernel_interface_t *this, chunk_t integrity_key, bool replace) { - netlink_message_t request, *response; - POS; - memset(&request, 0, sizeof(request)); - - request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - request.hdr.nlmsg_type = replace ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA; - - request.sa.saddr = me->get_xfrm_addr(me); - request.sa.id.daddr = other->get_xfrm_addr(other); - - request.sa.id.spi = spi; - request.sa.id.proto = protocol; - request.sa.family = me->get_family(me); - request.sa.mode = tunnel_mode; - request.sa.replay_window = 0; //sa->replay_window; ??? - request.sa.reqid = 0; //sa->reqid; ??? - 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.hard_packet_limit = XFRM_INF; - - request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.sa))); - - if (enc_alg != ENCR_UNDEFINED) - { + netlink_message_t request, *response; + memset(&request, 0, sizeof(request)); + + + request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + request.hdr.nlmsg_type = replace ? XFRM_MSG_UPDSA : XFRM_MSG_NEWSA; + + request.sa.saddr = me->get_xfrm_addr(me); + request.sa.id.daddr = other->get_xfrm_addr(other); + + request.sa.id.spi = spi; + /* TODO: this should be done with getprotobyname() */ + request.sa.id.proto = (protocol == ESP) ? KERNEL_ESP : KERNEL_AH; + request.sa.family = me->get_family(me); + request.sa.mode = tunnel_mode; + request.sa.replay_window = 0; //sa->replay_window; ??? + request.sa.reqid = 0; //sa->reqid; ??? + 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.hard_packet_limit = XFRM_INF; + + request.hdr.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(request.sa))); + + if (enc_alg != ENCR_UNDEFINED) + { netlink_algo_t *nla = (netlink_algo_t*)(((u_int8_t*)&request) + request.hdr.nlmsg_len); - - nla->type = XFRMA_ALG_CRYPT; + + nla->type = XFRMA_ALG_CRYPT; nla->length = sizeof(netlink_algo_t) + encryption_key.len; nla->algo.alg_key_len = encryption_key.len * 8; strcpy(nla->algo.alg_name, mapping_find(kernel_encryption_algs_m, enc_alg)); memcpy(nla->algo.alg_key, encryption_key.ptr, encryption_key.len); - + request.hdr.nlmsg_len += nla->length; - } - - if (int_alg != AUTH_UNDEFINED) - { + } + + if (int_alg != AUTH_UNDEFINED) + { netlink_algo_t *nla = (netlink_algo_t*)(((u_int8_t*)&request) + request.hdr.nlmsg_len); nla->type = XFRMA_ALG_AUTH; @@ -252,20 +258,20 @@ static status_t add_sa( private_kernel_interface_t *this, nla->algo.alg_key_len = integrity_key.len * 8; strcpy(nla->algo.alg_name, mapping_find(kernel_integrity_algs_m, int_alg)); memcpy(nla->algo.alg_key, integrity_key.ptr, integrity_key.len); - + request.hdr.nlmsg_len += nla->length; - } - - /* add IPComp */ - - if (this->send_message(this, &request, &response) != SUCCESS) - { - allocator_free(response); - return FAILED; - } - - allocator_free(response); - return SUCCESS; + } + + /* add IPComp here*/ + + if (this->send_message(this, &request, &response) != SUCCESS) + { + allocator_free(response); + return FAILED; + } + + allocator_free(response); + return SUCCESS; } @@ -276,7 +282,7 @@ static status_t send_message(private_kernel_interface_t *this, netlink_message_t request->hdr.nlmsg_seq = ++this->seq; request->hdr.nlmsg_pid = this->pid; - + memset(&addr, 0, sizeof(struct sockaddr_nl)); addr.nl_family = AF_NETLINK; addr.nl_pid = 0; @@ -308,17 +314,17 @@ static status_t send_message(private_kernel_interface_t *this, netlink_message_t if (listed_response->hdr.nlmsg_seq == request->hdr.nlmsg_seq) { /* matches our request, this is the reply */ - *response = listed_response; - found = TRUE; - break; - } - } - iterator->destroy(iterator); - - if (found) - { - break; - } + *response = listed_response; + found = TRUE; + break; + } + } + iterator->destroy(iterator); + + if (found) + { + break; + } /* we should time out, if something goes wrong */ pthread_cond_wait(&(this->condvar), &(this->mutex)); } @@ -330,16 +336,16 @@ static status_t send_message(private_kernel_interface_t *this, netlink_message_t static void receive_messages(private_kernel_interface_t *this) -{ +{ while(TRUE) { netlink_message_t response, *listed_response; while (TRUE) { - struct sockaddr_nl addr; + struct sockaddr_nl addr; socklen_t addr_length; size_t length; - + addr_length = sizeof(addr); response.hdr.nlmsg_type = XFRM_MSG_NEWSA; @@ -347,11 +353,11 @@ static void receive_messages(private_kernel_interface_t *this) if (length < 0) { if (errno == EINTR) - { - /* interrupted, try again */ + { + /* interrupted, try again */ continue; - } - charon->kill(charon, "receiving from netlink socket failed"); + } + charon->kill(charon, "receiving from netlink socket failed"); } if (!NLMSG_OK(&response.hdr, length)) { @@ -361,7 +367,7 @@ static void receive_messages(private_kernel_interface_t *this) if (addr.nl_pid != 0) { /* not from kernel. not interested, try another one */ - continue; + continue; } break; } diff --git a/Source/charon/threads/kernel_interface.h b/Source/charon/threads/kernel_interface.h index eeebbcdf8..7f57a04d6 100644 --- a/Source/charon/threads/kernel_interface.h +++ b/Source/charon/threads/kernel_interface.h @@ -54,8 +54,8 @@ struct kernel_interface_t { * @todo Cleanup method params */ status_t (*add_sa)(kernel_interface_t *this, - host_t *me, - host_t *other, + host_t *src, + host_t *dst, u_int32_t spi, int protocol, bool tunnel_mode, |