From 2a1c9e20bd38572ba32ba57436d7064192680729 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 15 Oct 2014 17:22:55 +0200 Subject: kernel-interface: Remove reqid parameter from get_spi/get_cpi() methods The reqid is not strictly required, as we set the reqid with the update call when installing the negotiated SA. If we don't need a reqid at this stage, we can later allocate the reqid in the kernel backend once the SA parameters have been fully negotaited. This allows us to assign the same reqid for the same selectors to avoid conflicts on backends this is necessary. --- .../plugins/kernel_pfkey/kernel_pfkey_ipsec.c | 23 ++++++++++------------ 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c') diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c index 6b5678270..1d24b7b15 100644 --- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c +++ b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c @@ -1518,7 +1518,7 @@ static bool receive_events(private_kernel_pfkey_ipsec_t *this, int fd, static status_t get_spi_internal(private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, u_int8_t proto, u_int32_t min, u_int32_t max, - u_int32_t reqid, u_int32_t *spi) + u_int32_t *spi) { unsigned char request[PFKEY_BUFFER_SIZE]; struct sadb_msg *msg, *out; @@ -1539,7 +1539,6 @@ static status_t get_spi_internal(private_kernel_pfkey_ipsec_t *this, sa2 = (struct sadb_x_sa2*)PFKEY_EXT_ADD_NEXT(msg); sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2; sa2->sadb_x_sa2_len = PFKEY_LEN(sizeof(struct sadb_spirange)); - sa2->sadb_x_sa2_reqid = reqid; PFKEY_EXT_ADD(msg, sa2); add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE); @@ -1577,39 +1576,37 @@ static status_t get_spi_internal(private_kernel_pfkey_ipsec_t *this, METHOD(kernel_ipsec_t, get_spi, status_t, private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, - u_int8_t protocol, u_int32_t reqid, u_int32_t *spi) + u_int8_t protocol, u_int32_t *spi) { - DBG2(DBG_KNL, "getting SPI for reqid {%u}", reqid); - if (get_spi_internal(this, src, dst, protocol, - 0xc0000000, 0xcFFFFFFF, reqid, spi) != SUCCESS) + 0xc0000000, 0xcFFFFFFF, spi) != SUCCESS) { - DBG1(DBG_KNL, "unable to get SPI for reqid {%u}", reqid); + DBG1(DBG_KNL, "unable to get SPI"); return FAILED; } - DBG2(DBG_KNL, "got SPI %.8x for reqid {%u}", ntohl(*spi), reqid); + DBG2(DBG_KNL, "got SPI %.8x", ntohl(*spi)); return SUCCESS; } METHOD(kernel_ipsec_t, get_cpi, status_t, private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, - u_int32_t reqid, u_int16_t *cpi) + u_int16_t *cpi) { u_int32_t received_spi = 0; - DBG2(DBG_KNL, "getting CPI for reqid {%u}", reqid); + DBG2(DBG_KNL, "getting CPI"); if (get_spi_internal(this, src, dst, IPPROTO_COMP, - 0x100, 0xEFFF, reqid, &received_spi) != SUCCESS) + 0x100, 0xEFFF, &received_spi) != SUCCESS) { - DBG1(DBG_KNL, "unable to get CPI for reqid {%u}", reqid); + DBG1(DBG_KNL, "unable to get CPI"); return FAILED; } *cpi = htons((u_int16_t)ntohl(received_spi)); - DBG2(DBG_KNL, "got CPI %.4x for reqid {%u}", ntohs(*cpi), reqid); + DBG2(DBG_KNL, "got CPI %.4x", ntohs(*cpi)); return SUCCESS; } -- cgit v1.2.3 From 6ad787ca54ba8f51dce8311dc8bb012a04581b96 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Fri, 17 Oct 2014 14:31:32 +0200 Subject: kernel-pfkey: Don't update during add_sa(), but delete SPI allocation state --- .../plugins/kernel_pfkey/kernel_pfkey_ipsec.c | 25 ++++++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c') diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c index 1d24b7b15..b46f19011 100644 --- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c +++ b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c @@ -1522,7 +1522,6 @@ static status_t get_spi_internal(private_kernel_pfkey_ipsec_t *this, { unsigned char request[PFKEY_BUFFER_SIZE]; struct sadb_msg *msg, *out; - struct sadb_x_sa2 *sa2; struct sadb_spirange *range; pfkey_msg_t response; u_int32_t received_spi = 0; @@ -1536,11 +1535,6 @@ static status_t get_spi_internal(private_kernel_pfkey_ipsec_t *this, msg->sadb_msg_satype = proto2satype(proto); msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); - sa2 = (struct sadb_x_sa2*)PFKEY_EXT_ADD_NEXT(msg); - sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2; - sa2->sadb_x_sa2_len = PFKEY_LEN(sizeof(struct sadb_spirange)); - PFKEY_EXT_ADD(msg, sa2); - add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0, FALSE); add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0, FALSE); @@ -1641,6 +1635,23 @@ METHOD(kernel_ipsec_t, add_sa, status_t, mode = MODE_TRANSPORT; } + if (inbound) + { + /* As we didn't know the reqid during SPI allocation, we used reqid + * zero. Unfortunately we can't SADB_UPDATE to the new reqid, hence we + * have to delete the SPI allocation state manually. The reqid + * selector does not count for that, therefore we have to delete + * that state before installing the new SA to avoid deleting the + * the new state after installing it. */ + mark_t zeromark = {0, 0}; + + if (this->public.interface.del_sa(&this->public.interface, + src, dst, spi, protocol, 0, zeromark) != SUCCESS) + { + DBG1(DBG_KNL, "deleting SPI allocation SA failed"); + } + } + memset(&request, 0, sizeof(request)); DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}", @@ -1648,7 +1659,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, msg = (struct sadb_msg*)request; msg->sadb_msg_version = PF_KEY_V2; - msg->sadb_msg_type = inbound ? SADB_UPDATE : SADB_ADD; + msg->sadb_msg_type = SADB_ADD; msg->sadb_msg_satype = proto2satype(protocol); msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); -- cgit v1.2.3 From d05d85fe658321aff8d859eaf50704a21299b683 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 15 Oct 2014 18:03:31 +0200 Subject: kernel-interface: Pass full list of traffic selectors to add_sa() While we can handle the first selector only in BEET mode in kernel-netlink, passing the full list gives the backend more flexibility how to handle this information. --- src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c') diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c index b46f19011..348549bfa 100644 --- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c +++ b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c @@ -1611,7 +1611,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi, u_int32_t replay_window, bool initiator, bool encap, bool esn, bool inbound, - traffic_selector_t *src_ts, traffic_selector_t *dst_ts) + linked_list_t *src_ts, linked_list_t *dst_ts) { unsigned char request[PFKEY_BUFFER_SIZE]; struct sadb_msg *msg, *out; -- cgit v1.2.3 From f81a9497483a7282c11adf5705d9ea3e83f6fffd Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Mon, 27 Oct 2014 15:07:05 +0100 Subject: kernel-interface: Raise expires with a proto/SPI/dst tuple instead of reqid --- .../plugins/kernel_pfkey/kernel_pfkey_ipsec.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c') diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c index 348549bfa..9b846864e 100644 --- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c +++ b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c @@ -1296,7 +1296,8 @@ static void process_expire(private_kernel_pfkey_ipsec_t *this, { pfkey_msg_t response; u_int8_t protocol; - u_int32_t spi, reqid; + u_int32_t spi; + host_t *dst; bool hard; DBG2(DBG_KNL, "received an SADB_EXPIRE"); @@ -1309,18 +1310,18 @@ static void process_expire(private_kernel_pfkey_ipsec_t *this, protocol = satype2proto(msg->sadb_msg_satype); spi = response.sa->sadb_sa_spi; - reqid = response.x_sa2->sadb_x_sa2_reqid; hard = response.lft_hard != NULL; - if (protocol != IPPROTO_ESP && protocol != IPPROTO_AH) + if (protocol == IPPROTO_ESP || protocol == IPPROTO_AH) { - DBG2(DBG_KNL, "ignoring SADB_EXPIRE for SA with SPI %.8x and " - "reqid {%u} which is not a CHILD_SA", ntohl(spi), reqid); - return; + dst = host_create_from_sockaddr((sockaddr_t*)(response.dst + 1)); + if (dst) + { + hydra->kernel_interface->expire(hydra->kernel_interface, protocol, + spi, dst, hard); + dst->destroy(dst); + } } - - hydra->kernel_interface->expire(hydra->kernel_interface, reqid, protocol, - spi, hard); } #ifdef SADB_X_MIGRATE -- cgit v1.2.3 From b125839a1a174936624ad99765ea451c55834a70 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Mon, 27 Oct 2014 15:38:47 +0100 Subject: kernel-interface: Raise mapping event with a proto/SPI/dst tuple --- .../plugins/kernel_pfkey/kernel_pfkey_ipsec.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c') diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c index 9b846864e..8b893f485 100644 --- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c +++ b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c @@ -1388,9 +1388,9 @@ static void process_mapping(private_kernel_pfkey_ipsec_t *this, struct sadb_msg* msg) { pfkey_msg_t response; - u_int32_t spi, reqid; + u_int32_t spi; sockaddr_t *sa; - host_t *host; + host_t *dst, *new; DBG2(DBG_KNL, "received an SADB_X_NAT_T_NEW_MAPPING"); @@ -1408,7 +1408,6 @@ static void process_mapping(private_kernel_pfkey_ipsec_t *this, } spi = response.sa->sadb_sa_spi; - reqid = response.x_sa2->sadb_x_sa2_reqid; if (satype2proto(msg->sadb_msg_satype) != IPPROTO_ESP) { @@ -1416,6 +1415,7 @@ static void process_mapping(private_kernel_pfkey_ipsec_t *this, } sa = (sockaddr_t*)(response.dst + 1); + dst = host_create_from_sockaddr(sa); switch (sa->sa_family) { case AF_INET: @@ -1433,12 +1433,16 @@ static void process_mapping(private_kernel_pfkey_ipsec_t *this, default: break; } - - host = host_create_from_sockaddr(sa); - if (host) + if (dst) { - hydra->kernel_interface->mapping(hydra->kernel_interface, reqid, - spi, host); + new = host_create_from_sockaddr(sa); + if (new) + { + hydra->kernel_interface->mapping(hydra->kernel_interface, + IPPROTO_ESP, spi, dst, new); + new->destroy(new); + } + dst->destroy(dst); } } #endif /*SADB_X_NAT_T_NEW_MAPPING*/ -- cgit v1.2.3