diff options
Diffstat (limited to 'src/libhydra/plugins/kernel_netlink')
4 files changed, 245 insertions, 216 deletions
diff --git a/src/libhydra/plugins/kernel_netlink/Makefile.in b/src/libhydra/plugins/kernel_netlink/Makefile.in index d293347cf..78dfb1b54 100644 --- a/src/libhydra/plugins/kernel_netlink/Makefile.in +++ b/src/libhydra/plugins/kernel_netlink/Makefile.in @@ -224,13 +224,7 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ ipsecdir = @ipsecdir@ -<<<<<<< HEAD -ipsecgid = @ipsecgid@ ipsecgroup = @ipsecgroup@ -ipsecuid = @ipsecuid@ -======= -ipsecgroup = @ipsecgroup@ ->>>>>>> upstream/4.5.1 ipsecuser = @ipsecuser@ libcharon_plugins = @libcharon_plugins@ libdir = @libdir@ @@ -251,6 +245,8 @@ nm_ca_dir = @nm_ca_dir@ oldincludedir = @oldincludedir@ openac_plugins = @openac_plugins@ p_plugins = @p_plugins@ +pcsclite_CFLAGS = @pcsclite_CFLAGS@ +pcsclite_LIBS = @pcsclite_LIBS@ pdfdir = @pdfdir@ piddir = @piddir@ pki_plugins = @pki_plugins@ @@ -269,14 +265,12 @@ sbindir = @sbindir@ scepclient_plugins = @scepclient_plugins@ scripts_plugins = @scripts_plugins@ sharedstatedir = @sharedstatedir@ -<<<<<<< HEAD -======= soup_CFLAGS = @soup_CFLAGS@ soup_LIBS = @soup_LIBS@ ->>>>>>> upstream/4.5.1 srcdir = @srcdir@ strongswan_conf = @strongswan_conf@ sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c index bd3f4a122..8b2a1aa77 100644 --- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c +++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c @@ -58,13 +58,11 @@ #endif /*IPV6_XFRM_POLICY*/ /** default priority of installed policies */ -<<<<<<< HEAD -#define PRIO_LOW 3000 -#define PRIO_HIGH 2000 -======= #define PRIO_LOW 1024 #define PRIO_HIGH 512 ->>>>>>> upstream/4.5.1 + +/** default replay window size, if not set using charon.replay_window */ +#define DEFAULT_REPLAY_WINDOW 32 /** * map the limit for bytes and packets to XFRM_INF per default @@ -353,6 +351,16 @@ struct private_kernel_netlink_ipsec_t { * whether to install routes along policies */ bool install_routes; + + /** + * Size of the replay window, in packets + */ + u_int32_t replay_window; + + /** + * Size of the replay window bitmap, in bytes + */ + u_int32_t replay_bmp; }; /** @@ -871,13 +879,9 @@ METHOD(kernel_ipsec_t, get_cpi, status_t, METHOD(kernel_ipsec_t, add_sa, status_t, private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark, -<<<<<<< HEAD - lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, -======= u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, ->>>>>>> upstream/4.5.1 u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp, - u_int16_t cpi, bool encap, bool inbound, + u_int16_t cpi, bool encap, bool esn, bool inbound, traffic_selector_t* src_ts, traffic_selector_t* dst_ts) { netlink_buf_t request; @@ -885,19 +889,16 @@ METHOD(kernel_ipsec_t, add_sa, status_t, struct nlmsghdr *hdr; struct xfrm_usersa_info *sa; u_int16_t icv_size = 64; + status_t status = FAILED; /* if IPComp is used, we install an additional IPComp SA. if the cpi is 0 * we are in the recursive call below */ if (ipcomp != IPCOMP_NONE && cpi != 0) { lifetime_cfg_t lft = {{0,0,0},{0,0,0},{0,0,0}}; -<<<<<<< HEAD - add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark, -======= add_sa(this, src, dst, htonl(ntohs(cpi)), IPPROTO_COMP, reqid, mark, tfc, ->>>>>>> upstream/4.5.1 &lft, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty, - mode, ipcomp, 0, FALSE, inbound, NULL, NULL); + mode, ipcomp, 0, FALSE, FALSE, inbound, NULL, NULL); ipcomp = IPCOMP_NONE; /* use transport mode ESP SA, IPComp uses tunnel mode */ mode = MODE_TRANSPORT; @@ -933,10 +934,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, sa->flags |= XFRM_STATE_AF_UNSPEC; break; case MODE_BEET: -<<<<<<< HEAD -======= case MODE_TRANSPORT: ->>>>>>> upstream/4.5.1 if(src_ts && dst_ts) { sa->sel = ts2selector(src_ts, dst_ts); @@ -946,7 +944,6 @@ METHOD(kernel_ipsec_t, add_sa, status_t, break; } - sa->replay_window = (protocol == IPPROTO_COMP) ? 0 : 32; sa->reqid = reqid; sa->lft.soft_byte_limit = XFRM_LIMIT(lifetime->bytes.rekey); sa->lft.hard_byte_limit = XFRM_LIMIT(lifetime->bytes.life); @@ -987,17 +984,17 @@ METHOD(kernel_ipsec_t, add_sa, status_t, { DBG1(DBG_KNL, "algorithm %N not supported by kernel!", encryption_algorithm_names, enc_alg); - return FAILED; + goto failed; } DBG2(DBG_KNL, " using encryption algorithm %N with key size %d", encryption_algorithm_names, enc_alg, enc_key.len * 8); rthdr->rta_type = XFRMA_ALG_AEAD; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_aead) + enc_key.len); - hdr->nlmsg_len += rthdr->rta_len; + hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { - return FAILED; + goto failed; } algo = (struct xfrm_algo_aead*)RTA_DATA(rthdr); @@ -1018,17 +1015,17 @@ METHOD(kernel_ipsec_t, add_sa, status_t, { DBG1(DBG_KNL, "algorithm %N not supported by kernel!", encryption_algorithm_names, enc_alg); - return FAILED; + goto failed; } DBG2(DBG_KNL, " using encryption algorithm %N with key size %d", encryption_algorithm_names, enc_alg, enc_key.len * 8); rthdr->rta_type = XFRMA_ALG_CRYPT; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + enc_key.len); - hdr->nlmsg_len += rthdr->rta_len; + hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { - return FAILED; + goto failed; } algo = (struct xfrm_algo*)RTA_DATA(rthdr); @@ -1047,7 +1044,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, { DBG1(DBG_KNL, "algorithm %N not supported by kernel!", integrity_algorithm_names, int_alg); - return FAILED; + goto failed; } DBG2(DBG_KNL, " using integrity algorithm %N with key size %d", integrity_algorithm_names, int_alg, int_key.len * 8); @@ -1061,10 +1058,10 @@ METHOD(kernel_ipsec_t, add_sa, status_t, rthdr->rta_type = XFRMA_ALG_AUTH_TRUNC; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_auth) + int_key.len); - hdr->nlmsg_len += rthdr->rta_len; + hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { - return FAILED; + goto failed; } algo = (struct xfrm_algo_auth*)RTA_DATA(rthdr); @@ -1080,10 +1077,10 @@ METHOD(kernel_ipsec_t, add_sa, status_t, rthdr->rta_type = XFRMA_ALG_AUTH; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + int_key.len); - hdr->nlmsg_len += rthdr->rta_len; + hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { - return FAILED; + goto failed; } algo = (struct xfrm_algo*)RTA_DATA(rthdr); @@ -1102,16 +1099,16 @@ METHOD(kernel_ipsec_t, add_sa, status_t, { DBG1(DBG_KNL, "algorithm %N not supported by kernel!", ipcomp_transform_names, ipcomp); - return FAILED; + goto failed; } DBG2(DBG_KNL, " using compression algorithm %N", ipcomp_transform_names, ipcomp); rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo)); - hdr->nlmsg_len += rthdr->rta_len; + hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { - return FAILED; + goto failed; } struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr); @@ -1128,10 +1125,10 @@ METHOD(kernel_ipsec_t, add_sa, status_t, rthdr->rta_type = XFRMA_ENCAP; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl)); - hdr->nlmsg_len += rthdr->rta_len; + hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { - return FAILED; + goto failed; } tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr); @@ -1158,10 +1155,10 @@ METHOD(kernel_ipsec_t, add_sa, status_t, rthdr->rta_type = XFRMA_MARK; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += rthdr->rta_len; + hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { - return FAILED; + goto failed; } mrk = (struct xfrm_mark*)RTA_DATA(rthdr); @@ -1170,8 +1167,6 @@ METHOD(kernel_ipsec_t, add_sa, status_t, rthdr = XFRM_RTA_NEXT(rthdr); } -<<<<<<< HEAD -======= if (tfc) { u_int32_t *tfcpad; @@ -1179,10 +1174,10 @@ METHOD(kernel_ipsec_t, add_sa, status_t, rthdr->rta_type = XFRMA_TFCPAD; rthdr->rta_len = RTA_LENGTH(sizeof(u_int32_t)); - hdr->nlmsg_len += rthdr->rta_len; + hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { - return FAILED; + goto failed; } tfcpad = (u_int32_t*)RTA_DATA(rthdr); @@ -1190,7 +1185,41 @@ METHOD(kernel_ipsec_t, add_sa, status_t, rthdr = XFRM_RTA_NEXT(rthdr); } ->>>>>>> upstream/4.5.1 + if (protocol != IPPROTO_COMP) + { + if (esn || this->replay_window > DEFAULT_REPLAY_WINDOW) + { + /* for ESN or larger replay windows we need the new + * XFRMA_REPLAY_ESN_VAL attribute to configure a bitmap */ + struct xfrm_replay_state_esn *replay; + + rthdr->rta_type = XFRMA_REPLAY_ESN_VAL; + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state_esn) + + (this->replay_window + 7) / 8); + + hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); + if (hdr->nlmsg_len > sizeof(request)) + { + goto failed; + } + + replay = (struct xfrm_replay_state_esn*)RTA_DATA(rthdr); + /* bmp_len contains number uf __u32's */ + replay->bmp_len = this->replay_bmp; + replay->replay_window = this->replay_window; + + rthdr = XFRM_RTA_NEXT(rthdr); + if (esn) + { + sa->flags |= XFRM_STATE_ESN; + } + } + else + { + sa->replay_window = DEFAULT_REPLAY_WINDOW; + } + } + if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS) { if (mark.value) @@ -1202,17 +1231,25 @@ METHOD(kernel_ipsec_t, add_sa, status_t, { DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi)); } - return FAILED; + goto failed; } - return SUCCESS; + + status = SUCCESS; + +failed: + memwipe(request, sizeof(request)); + return status; } /** - * Get the replay state (i.e. sequence numbers) of an SA. + * Get the ESN replay state (i.e. sequence numbers) of an SA. + * + * Allocates into one the replay state structure we get from the kernel. */ -static status_t get_replay_state(private_kernel_netlink_ipsec_t *this, - u_int32_t spi, u_int8_t protocol, host_t *dst, - struct xfrm_replay_state *replay) +static void get_replay_state(private_kernel_netlink_ipsec_t *this, + u_int32_t spi, u_int8_t protocol, host_t *dst, + struct xfrm_replay_state_esn **replay_esn, + struct xfrm_replay_state **replay) { netlink_buf_t request; struct nlmsghdr *hdr, *out = NULL; @@ -1223,7 +1260,8 @@ static status_t get_replay_state(private_kernel_netlink_ipsec_t *this, memset(&request, 0, sizeof(request)); - DBG2(DBG_KNL, "querying replay state from SAD entry with SPI %.8x", ntohl(spi)); + DBG2(DBG_KNL, "querying replay state from SAD entry with SPI %.8x", + ntohl(spi)); hdr = (struct nlmsghdr*)request; hdr->nlmsg_flags = NLM_F_REQUEST; @@ -1267,32 +1305,30 @@ static status_t get_replay_state(private_kernel_netlink_ipsec_t *this, } } - if (out_aevent == NULL) - { - DBG1(DBG_KNL, "unable to query replay state from SAD entry with SPI %.8x", - ntohl(spi)); - free(out); - return FAILED; - } - - rta = XFRM_RTA(out, struct xfrm_aevent_id); - rtasize = XFRM_PAYLOAD(out, struct xfrm_aevent_id); - while(RTA_OK(rta, rtasize)) + if (out_aevent) { - if (rta->rta_type == XFRMA_REPLAY_VAL && - RTA_PAYLOAD(rta) == sizeof(struct xfrm_replay_state)) + rta = XFRM_RTA(out, struct xfrm_aevent_id); + rtasize = XFRM_PAYLOAD(out, struct xfrm_aevent_id); + while (RTA_OK(rta, rtasize)) { - memcpy(replay, RTA_DATA(rta), RTA_PAYLOAD(rta)); - free(out); - return SUCCESS; + if (rta->rta_type == XFRMA_REPLAY_VAL && + RTA_PAYLOAD(rta) == sizeof(**replay)) + { + *replay = malloc(RTA_PAYLOAD(rta)); + memcpy(*replay, RTA_DATA(rta), RTA_PAYLOAD(rta)); + break; + } + if (rta->rta_type == XFRMA_REPLAY_ESN_VAL && + RTA_PAYLOAD(rta) >= sizeof(**replay_esn) + this->replay_bmp) + { + *replay_esn = malloc(RTA_PAYLOAD(rta)); + memcpy(*replay_esn, RTA_DATA(rta), RTA_PAYLOAD(rta)); + break; + } + rta = RTA_NEXT(rta, rtasize); } - rta = RTA_NEXT(rta, rtasize); } - - DBG1(DBG_KNL, "unable to query replay state from SAD entry with SPI %.8x", - ntohl(spi)); free(out); - return FAILED; } METHOD(kernel_ipsec_t, query_sa, status_t, @@ -1303,6 +1339,7 @@ METHOD(kernel_ipsec_t, query_sa, status_t, struct nlmsghdr *out = NULL, *hdr; struct xfrm_usersa_id *sa_id; struct xfrm_usersa_info *sa = NULL; + status_t status = FAILED; size_t len; memset(&request, 0, sizeof(request)); @@ -1334,7 +1371,7 @@ METHOD(kernel_ipsec_t, query_sa, status_t, rthdr->rta_type = XFRMA_MARK; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += rthdr->rta_len; + hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { return FAILED; @@ -1389,13 +1426,15 @@ METHOD(kernel_ipsec_t, query_sa, status_t, if (sa == NULL) { DBG2(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi)); - free(out); - return FAILED; } - *bytes = sa->curlft.bytes; - + else + { + *bytes = sa->curlft.bytes; + status = SUCCESS; + } + memwipe(out, len); free(out); - return SUCCESS; + return status; } METHOD(kernel_ipsec_t, del_sa, status_t, @@ -1441,7 +1480,7 @@ METHOD(kernel_ipsec_t, del_sa, status_t, rthdr->rta_type = XFRMA_MARK; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += rthdr->rta_len; + hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { return FAILED; @@ -1491,8 +1530,9 @@ METHOD(kernel_ipsec_t, update_sa, status_t, struct rtattr *rta; size_t rtasize; struct xfrm_encap_tmpl* tmpl = NULL; - bool got_replay_state = FALSE; - struct xfrm_replay_state replay; + struct xfrm_replay_state *replay = NULL; + struct xfrm_replay_state_esn *replay_esn = NULL; + status_t status = FAILED; /* if IPComp is used, we first update the IPComp SA */ if (cpi) @@ -1548,22 +1588,16 @@ METHOD(kernel_ipsec_t, update_sa, status_t, if (out_sa == NULL) { DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi)); - free(out); - return FAILED; + goto failed; } - /* try to get the replay state */ - if (get_replay_state(this, spi, protocol, dst, &replay) == SUCCESS) - { - got_replay_state = TRUE; - } + get_replay_state(this, spi, protocol, dst, &replay_esn, &replay); /* delete the old SA (without affecting the IPComp SA) */ if (del_sa(this, src, dst, spi, protocol, 0, mark) != SUCCESS) { DBG1(DBG_KNL, "unable to delete old SAD entry with SPI %.8x", ntohl(spi)); - free(out); - return FAILED; + goto failed; } DBG2(DBG_KNL, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H", @@ -1613,10 +1647,10 @@ METHOD(kernel_ipsec_t, update_sa, status_t, rta->rta_type = XFRMA_ENCAP; rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl)); - hdr->nlmsg_len += rta->rta_len; + hdr->nlmsg_len += RTA_ALIGN(rta->rta_len); if (hdr->nlmsg_len > sizeof(request)) { - return FAILED; + goto failed; } tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rta); @@ -1628,30 +1662,56 @@ METHOD(kernel_ipsec_t, update_sa, status_t, rta = XFRM_RTA_NEXT(rta); } - if (got_replay_state) - { /* copy the replay data if available */ + if (replay_esn) + { + rta->rta_type = XFRMA_REPLAY_ESN_VAL; + rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state_esn) + + this->replay_bmp); + + hdr->nlmsg_len += RTA_ALIGN(rta->rta_len); + if (hdr->nlmsg_len > sizeof(request)) + { + goto failed; + } + memcpy(RTA_DATA(rta), replay_esn, + sizeof(struct xfrm_replay_state_esn) + this->replay_bmp); + + rta = XFRM_RTA_NEXT(rta); + } + else if (replay) + { rta->rta_type = XFRMA_REPLAY_VAL; rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state)); - hdr->nlmsg_len += rta->rta_len; + hdr->nlmsg_len += RTA_ALIGN(rta->rta_len); if (hdr->nlmsg_len > sizeof(request)) { - return FAILED; + goto failed; } - memcpy(RTA_DATA(rta), &replay, sizeof(replay)); + memcpy(RTA_DATA(rta), replay, sizeof(replay)); rta = XFRM_RTA_NEXT(rta); } + else + { + DBG1(DBG_KNL, "unable to copy replay state from old SAD entry " + "with SPI %.8x", ntohl(spi)); + } if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS) { DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi)); - free(out); - return FAILED; + goto failed; } + + status = SUCCESS; +failed: + free(replay); + free(replay_esn); + memwipe(out, len); free(out); - return SUCCESS; + return status; } METHOD(kernel_ipsec_t, add_policy, status_t, @@ -1725,13 +1785,6 @@ METHOD(kernel_ipsec_t, add_policy, status_t, policy_info = (struct xfrm_userpolicy_info*)NLMSG_DATA(hdr); policy_info->sel = policy->sel; policy_info->dir = policy->direction; -<<<<<<< HEAD - /* calculate priority based on source selector size, small size = high prio */ - policy_info->priority = routed ? PRIO_LOW : PRIO_HIGH; - policy_info->priority -= policy->sel.prefixlen_s * 10; - policy_info->priority -= policy->sel.proto ? 2 : 0; - policy_info->priority -= policy->sel.sport_mask ? 1 : 0; -======= /* calculate priority based on selector size, small size = high prio */ policy_info->priority = routed ? PRIO_LOW : PRIO_HIGH; @@ -1742,7 +1795,6 @@ METHOD(kernel_ipsec_t, add_policy, status_t, policy->sel.dport_mask ? 0 : 2; policy_info->priority += policy->sel.proto ? 0 : 1; ->>>>>>> upstream/4.5.1 policy_info->action = type != POLICY_DROP ? XFRM_POLICY_ALLOW : XFRM_POLICY_BLOCK; policy_info->share = XFRM_SHARE_ANY; @@ -1784,7 +1836,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t, } rthdr->rta_len += RTA_LENGTH(sizeof(struct xfrm_user_tmpl)); - hdr->nlmsg_len += RTA_LENGTH(sizeof(struct xfrm_user_tmpl)); + hdr->nlmsg_len += RTA_ALIGN(RTA_LENGTH(sizeof(struct xfrm_user_tmpl))); if (hdr->nlmsg_len > sizeof(request)) { return FAILED; @@ -1820,7 +1872,7 @@ METHOD(kernel_ipsec_t, add_policy, status_t, rthdr->rta_type = XFRMA_MARK; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += rthdr->rta_len; + hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { return FAILED; @@ -1864,11 +1916,8 @@ METHOD(kernel_ipsec_t, add_policy, status_t, if (route->if_name) { -<<<<<<< HEAD -======= DBG2(DBG_KNL, "installing route: %R via %H src %H dev %s", src_ts, route->gateway, route->src_ip, route->if_name); ->>>>>>> upstream/4.5.1 switch (hydra->kernel_interface->add_route( hydra->kernel_interface, route->dst_net, route->prefixlen, route->gateway, @@ -1942,7 +1991,7 @@ METHOD(kernel_ipsec_t, query_policy, status_t, rthdr->rta_type = XFRMA_MARK; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += rthdr->rta_len; + hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { return FAILED; @@ -2084,7 +2133,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t, rthdr->rta_type = XFRMA_MARK; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += rthdr->rta_len; + hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { return FAILED; @@ -2225,10 +2274,14 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create() (hashtable_equals_t)policy_equals, 32), .mutex = mutex_create(MUTEX_TYPE_DEFAULT), .install_routes = lib->settings->get_bool(lib->settings, - "%s.install_routes", TRUE, - hydra->daemon), + "%s.install_routes", TRUE, hydra->daemon), + .replay_window = lib->settings->get_int(lib->settings, + "%s.replay_window", DEFAULT_REPLAY_WINDOW, hydra->daemon), ); + this->replay_bmp = (this->replay_window + sizeof(u_int32_t) * 8 - 1) / + (sizeof(u_int32_t) * 8); + if (streq(hydra->daemon, "pluto")) { /* no routes for pluto, they are installed via updown script */ this->install_routes = FALSE; diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c index 314c1acc1..8315ed310 100644 --- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c +++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c @@ -350,7 +350,7 @@ static void process_link(private_kernel_netlink_net_t *this, entry->addrs = linked_list_create(); this->ifaces->insert_last(this->ifaces, entry); } - memcpy(entry->ifname, name, IFNAMSIZ); + strncpy(entry->ifname, name, IFNAMSIZ); entry->ifname[IFNAMSIZ-1] = '\0'; if (event) { @@ -534,6 +534,7 @@ static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *h switch (rta->rta_type) { case RTA_PREFSRC: + DESTROY_IF(host); host = host_create_from_chunk(msg->rtm_family, chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)), 0); break; @@ -652,7 +653,8 @@ static void address_enumerator_destroy(address_enumerator_t *data) /** * filter for addresses */ -static bool filter_addresses(address_enumerator_t *data, addr_entry_t** in, host_t** out) +static bool filter_addresses(address_enumerator_t *data, + addr_entry_t** in, host_t** out) { if (!data->include_virtual_ips && (*in)->virtual) { /* skip virtual interfaces added by us */ @@ -669,16 +671,19 @@ static bool filter_addresses(address_enumerator_t *data, addr_entry_t** in, host /** * enumerator constructor for interfaces */ -static enumerator_t *create_iface_enumerator(iface_entry_t *iface, address_enumerator_t *data) +static enumerator_t *create_iface_enumerator(iface_entry_t *iface, + address_enumerator_t *data) { - return enumerator_create_filter(iface->addrs->create_enumerator(iface->addrs), + return enumerator_create_filter( + iface->addrs->create_enumerator(iface->addrs), (void*)filter_addresses, data, NULL); } /** * filter for interfaces */ -static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in, iface_entry_t** out) +static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in, + iface_entry_t** out) { if (!data->include_down_ifaces && !((*in)->flags & IFF_UP)) { /* skip interfaces not up */ @@ -688,11 +693,9 @@ static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in, if return TRUE; } -/** - * implementation of kernel_net_t.create_address_enumerator - */ -static enumerator_t *create_address_enumerator(private_kernel_netlink_net_t *this, - bool include_down_ifaces, bool include_virtual_ips) +METHOD(kernel_net_t, create_address_enumerator, enumerator_t*, + private_kernel_netlink_net_t *this, + bool include_down_ifaces, bool include_virtual_ips) { address_enumerator_t *data = malloc_thing(address_enumerator_t); data->this = this; @@ -701,15 +704,15 @@ static enumerator_t *create_address_enumerator(private_kernel_netlink_net_t *thi this->mutex->lock(this->mutex); return enumerator_create_nested( - enumerator_create_filter(this->ifaces->create_enumerator(this->ifaces), - (void*)filter_interfaces, data, NULL), - (void*)create_iface_enumerator, data, (void*)address_enumerator_destroy); + enumerator_create_filter( + this->ifaces->create_enumerator(this->ifaces), + (void*)filter_interfaces, data, NULL), + (void*)create_iface_enumerator, data, + (void*)address_enumerator_destroy); } -/** - * implementation of kernel_net_t.get_interface_name - */ -static char *get_interface_name(private_kernel_netlink_net_t *this, host_t* ip) +METHOD(kernel_net_t, get_interface_name, char*, + private_kernel_netlink_net_t *this, host_t* ip) { enumerator_t *ifaces, *addrs; iface_entry_t *iface; @@ -1036,19 +1039,14 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest, return src; } -/** - * Implementation of kernel_net_t.get_source_addr. - */ -static host_t* get_source_addr(private_kernel_netlink_net_t *this, - host_t *dest, host_t *src) +METHOD(kernel_net_t, get_source_addr, host_t*, + private_kernel_netlink_net_t *this, host_t *dest, host_t *src) { return get_route(this, dest, FALSE, src); } -/** - * Implementation of kernel_net_t.get_nexthop. - */ -static host_t* get_nexthop(private_kernel_netlink_net_t *this, host_t *dest) +METHOD(kernel_net_t, get_nexthop, host_t*, + private_kernel_netlink_net_t *this, host_t *dest) { return get_route(this, dest, TRUE, NULL); } @@ -1086,11 +1084,8 @@ static status_t manage_ipaddr(private_kernel_netlink_net_t *this, int nlmsg_type return this->socket->send_ack(this->socket, hdr); } -/** - * Implementation of kernel_net_t.add_ip. - */ -static status_t add_ip(private_kernel_netlink_net_t *this, - host_t *virtual_ip, host_t *iface_ip) +METHOD(kernel_net_t, add_ip, status_t, + private_kernel_netlink_net_t *this, host_t *virtual_ip, host_t *iface_ip) { iface_entry_t *iface; addr_entry_t *addr; @@ -1165,10 +1160,8 @@ static status_t add_ip(private_kernel_netlink_net_t *this, return FAILED; } -/** - * Implementation of kernel_net_t.del_ip. - */ -static status_t del_ip(private_kernel_netlink_net_t *this, host_t *virtual_ip) +METHOD(kernel_net_t, del_ip, status_t, + private_kernel_netlink_net_t *this, host_t *virtual_ip) { iface_entry_t *iface; addr_entry_t *addr; @@ -1296,21 +1289,17 @@ static status_t manage_srcroute(private_kernel_netlink_net_t *this, int nlmsg_ty return this->socket->send_ack(this->socket, hdr); } -/** - * Implementation of kernel_net_t.add_route. - */ -static status_t add_route(private_kernel_netlink_net_t *this, chunk_t dst_net, - u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name) +METHOD(kernel_net_t, add_route, status_t, + private_kernel_netlink_net_t *this, chunk_t dst_net, u_int8_t prefixlen, + host_t *gateway, host_t *src_ip, char *if_name) { return manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, dst_net, prefixlen, gateway, src_ip, if_name); } -/** - * Implementation of kernel_net_t.del_route. - */ -static status_t del_route(private_kernel_netlink_net_t *this, chunk_t dst_net, - u_int8_t prefixlen, host_t *gateway, host_t *src_ip, char *if_name) +METHOD(kernel_net_t, del_route, status_t, + private_kernel_netlink_net_t *this, chunk_t dst_net, u_int8_t prefixlen, + host_t *gateway, host_t *src_ip, char *if_name) { return manage_srcroute(this, RTM_DELROUTE, 0, dst_net, prefixlen, gateway, src_ip, if_name); @@ -1441,10 +1430,8 @@ static status_t manage_rule(private_kernel_netlink_net_t *this, int nlmsg_type, return this->socket->send_ack(this->socket, hdr); } -/** - * Implementation of kernel_netlink_net_t.destroy. - */ -static void destroy(private_kernel_netlink_net_t *this) +METHOD(kernel_net_t, destroy, void, + private_kernel_netlink_net_t *this) { if (this->routing_table) { @@ -1474,37 +1461,41 @@ static void destroy(private_kernel_netlink_net_t *this) */ kernel_netlink_net_t *kernel_netlink_net_create() { - private_kernel_netlink_net_t *this = malloc_thing(private_kernel_netlink_net_t); + private_kernel_netlink_net_t *this; struct sockaddr_nl addr; enumerator_t *enumerator; char *exclude; - /* public functions */ - this->public.interface.get_interface = (char*(*)(kernel_net_t*,host_t*))get_interface_name; - this->public.interface.create_address_enumerator = (enumerator_t*(*)(kernel_net_t*,bool,bool))create_address_enumerator; - this->public.interface.get_source_addr = (host_t*(*)(kernel_net_t*, host_t *dest, host_t *src))get_source_addr; - this->public.interface.get_nexthop = (host_t*(*)(kernel_net_t*, host_t *dest))get_nexthop; - this->public.interface.add_ip = (status_t(*)(kernel_net_t*,host_t*,host_t*)) add_ip; - this->public.interface.del_ip = (status_t(*)(kernel_net_t*,host_t*)) del_ip; - this->public.interface.add_route = (status_t(*)(kernel_net_t*,chunk_t,u_int8_t,host_t*,host_t*,char*)) add_route; - this->public.interface.del_route = (status_t(*)(kernel_net_t*,chunk_t,u_int8_t,host_t*,host_t*,char*)) del_route; - this->public.interface.destroy = (void(*)(kernel_net_t*)) destroy; - - /* private members */ - this->ifaces = linked_list_create(); - this->mutex = mutex_create(MUTEX_TYPE_RECURSIVE); - this->condvar = condvar_create(CONDVAR_TYPE_DEFAULT); + INIT(this, + .public = { + .interface = { + .get_interface = _get_interface_name, + .create_address_enumerator = _create_address_enumerator, + .get_source_addr = _get_source_addr, + .get_nexthop = _get_nexthop, + .add_ip = _add_ip, + .del_ip = _del_ip, + .add_route = _add_route, + .del_route = _del_route, + .destroy = _destroy, + }, + }, + .socket = netlink_socket_create(NETLINK_ROUTE), + .rt_exclude = linked_list_create(), + .ifaces = linked_list_create(), + .mutex = mutex_create(MUTEX_TYPE_RECURSIVE), + .condvar = condvar_create(CONDVAR_TYPE_DEFAULT), + .routing_table = lib->settings->get_int(lib->settings, + "%s.routing_table", ROUTING_TABLE, hydra->daemon), + .routing_table_prio = lib->settings->get_int(lib->settings, + "%s.routing_table_prio", ROUTING_TABLE_PRIO, hydra->daemon), + .process_route = lib->settings->get_bool(lib->settings, + "%s.process_route", TRUE, hydra->daemon), + .install_virtual_ip = lib->settings->get_bool(lib->settings, + "%s.install_virtual_ip", TRUE, hydra->daemon), + ); timerclear(&this->last_roam); - this->routing_table = lib->settings->get_int(lib->settings, - "%s.routing_table", ROUTING_TABLE, hydra->daemon); - this->routing_table_prio = lib->settings->get_int(lib->settings, - "%s.routing_table_prio", ROUTING_TABLE_PRIO, hydra->daemon); - this->process_route = lib->settings->get_bool(lib->settings, - "%s.process_route", TRUE, hydra->daemon); - this->install_virtual_ip = lib->settings->get_bool(lib->settings, - "%s.install_virtual_ip", TRUE, hydra->daemon); - - this->rt_exclude = linked_list_create(); + exclude = lib->settings->get_str(lib->settings, "%s.ignore_routing_tables", NULL, hydra->daemon); if (exclude) @@ -1526,9 +1517,6 @@ kernel_netlink_net_t *kernel_netlink_net_create() enumerator->destroy(enumerator); } - this->socket = netlink_socket_create(NETLINK_ROUTE); - this->job = NULL; - memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.c index b75a2be80..779466472 100644 --- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.c +++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_plugin.c @@ -33,15 +33,14 @@ struct private_kernel_netlink_plugin_t { kernel_netlink_plugin_t public; }; -<<<<<<< HEAD -/** - * Implementation of plugin_t.destroy - */ -static void destroy(private_kernel_netlink_plugin_t *this) -======= +METHOD(plugin_t, get_name, char*, + private_kernel_netlink_plugin_t *this) +{ + return "kernel-netlink"; +} + METHOD(plugin_t, destroy, void, private_kernel_netlink_plugin_t *this) ->>>>>>> upstream/4.5.1 { hydra->kernel_interface->remove_ipsec_interface(hydra->kernel_interface, (kernel_ipsec_constructor_t)kernel_netlink_ipsec_create); @@ -55,22 +54,17 @@ METHOD(plugin_t, destroy, void, */ plugin_t *kernel_netlink_plugin_create() { -<<<<<<< HEAD - private_kernel_netlink_plugin_t *this = malloc_thing(private_kernel_netlink_plugin_t); - - this->public.plugin.destroy = (void(*)(plugin_t*))destroy; - -======= private_kernel_netlink_plugin_t *this; INIT(this, .public = { .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, .destroy = _destroy, }, }, ); ->>>>>>> upstream/4.5.1 hydra->kernel_interface->add_ipsec_interface(hydra->kernel_interface, (kernel_ipsec_constructor_t)kernel_netlink_ipsec_create); hydra->kernel_interface->add_net_interface(hydra->kernel_interface, |