_(ipsec_sa_set_key_reply) \
_(ipsec_tunnel_if_add_del_reply) \
_(ipsec_tunnel_if_set_key_reply) \
+_(ipsec_tunnel_if_set_sa_reply) \
_(ikev2_profile_add_del_reply) \
_(ikev2_profile_set_auth_reply) \
_(ikev2_profile_set_id_reply) \
_(IPSEC_SA_SET_KEY_REPLY, ipsec_sa_set_key_reply) \
_(IPSEC_TUNNEL_IF_ADD_DEL_REPLY, ipsec_tunnel_if_add_del_reply) \
_(IPSEC_TUNNEL_IF_SET_KEY_REPLY, ipsec_tunnel_if_set_key_reply) \
+_(IPSEC_TUNNEL_IF_SET_SA_REPLY, ipsec_tunnel_if_set_sa_reply) \
_(IKEV2_PROFILE_ADD_DEL_REPLY, ikev2_profile_add_del_reply) \
_(IKEV2_PROFILE_SET_AUTH_REPLY, ikev2_profile_set_auth_reply) \
_(IKEV2_PROFILE_SET_ID_REPLY, ikev2_profile_set_id_reply) \
return ret;
}
+static int
+api_ipsec_tunnel_if_set_sa (vat_main_t * vam)
+{
+ unformat_input_t *i = vam->input;
+ vl_api_ipsec_tunnel_if_set_sa_t *mp;
+ u32 sw_if_index = ~0;
+ u32 sa_id = ~0;
+ u8 is_outbound = (u8) ~ 0;
+ int ret;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
+ ;
+ else if (unformat (i, "sa_id %d", &sa_id))
+ ;
+ else if (unformat (i, "outbound"))
+ is_outbound = 1;
+ else if (unformat (i, "inbound"))
+ is_outbound = 0;
+ else
+ {
+ clib_warning ("parse error '%U'", format_unformat_error, i);
+ return -99;
+ }
+ }
+
+ if (sw_if_index == ~0)
+ {
+ errmsg ("interface must be specified");
+ return -99;
+ }
+
+ if (sa_id == ~0)
+ {
+ errmsg ("SA ID must be specified");
+ return -99;
+ }
+
+ M (IPSEC_TUNNEL_IF_SET_SA, mp);
+
+ mp->sw_if_index = htonl (sw_if_index);
+ mp->sa_id = htonl (sa_id);
+ mp->is_outbound = is_outbound;
+
+ S (mp);
+ W (ret);
+
+ return ret;
+}
+
static int
api_ikev2_profile_add_del (vat_main_t * vam)
{
_(ipsec_sa_dump, "[sa_id <n>]") \
_(ipsec_tunnel_if_set_key, "<intfc> <local|remote> <crypto|integ>\n" \
" <alg> <hex>\n") \
+_(ipsec_tunnel_if_set_sa, "<intfc> sa_id <n> <inbound|outbound>\n") \
_(ikev2_profile_add_del, "name <profile_name> [del]") \
_(ikev2_profile_set_auth, "name <profile_name> auth_method <method>\n" \
"(auth_data 0x<data> | auth_data <data>)") \
u8 integrity_key[128];
u8 use_extended_sequence_number;
+ u8 use_anti_replay;
u8 is_tunnel;
u8 is_tunnel_ipv6;
u8 key[128];
};
+/** \brief Set new SA on IPsec interface
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param sw_if_index - index of tunnel interface
+ @param sa_id - ID of SA to use
+ @param is_outbound - 1 if outbound (local) SA, 0 if inbound (remote)
+*/
+autoreply define ipsec_tunnel_if_set_sa {
+ u32 client_index;
+ u32 context;
+ u32 sw_if_index;
+ u32 sa_id;
+ u8 is_outbound;
+};
+
/*
* Local Variables:
* eval: (c-set-style "gnu")
return 0;
}
-static u8
+u8
ipsec_is_sa_used (u32 sa_index)
{
ipsec_main_t *im = &ipsec_main;
int ipsec_set_sa_key (vlib_main_t * vm, ipsec_sa_t * sa_update);
u32 ipsec_get_sa_index_by_sa_id (u32 sa_id);
+u8 ipsec_is_sa_used (u32 sa_index);
u8 *format_ipsec_if_output_trace (u8 * s, va_list * args);
u8 *format_ipsec_policy_action (u8 * s, va_list * args);
u8 *format_ipsec_crypto_alg (u8 * s, va_list * args);
args);
int ipsec_set_interface_key (vnet_main_t * vnm, u32 hw_if_index,
ipsec_if_set_key_type_t type, u8 alg, u8 * key);
+int ipsec_set_interface_sa (vnet_main_t * vnm, u32 hw_if_index, u32 sa_id,
+ u8 is_outbound);
/*
_(IPSEC_SPD_DUMP, ipsec_spd_dump) \
_(IPSEC_TUNNEL_IF_ADD_DEL, ipsec_tunnel_if_add_del) \
_(IPSEC_TUNNEL_IF_SET_KEY, ipsec_tunnel_if_set_key) \
+_(IPSEC_TUNNEL_IF_SET_SA, ipsec_tunnel_if_set_sa) \
_(IKEV2_PROFILE_ADD_DEL, ikev2_profile_add_del) \
_(IKEV2_PROFILE_SET_AUTH, ikev2_profile_set_auth) \
_(IKEV2_PROFILE_SET_ID, ikev2_profile_set_id) \
clib_memcpy (&sa.tunnel_src_addr.ip4.data, mp->tunnel_src_address, 4);
clib_memcpy (&sa.tunnel_dst_addr.ip4.data, mp->tunnel_dst_address, 4);
}
+ sa.use_anti_replay = mp->use_anti_replay;
ASSERT (im->cb.check_support_cb);
clib_error_t *err = im->cb.check_support_cb (&sa);
}
+static void
+vl_api_ipsec_tunnel_if_set_sa_t_handler (vl_api_ipsec_tunnel_if_set_sa_t * mp)
+{
+ vl_api_ipsec_tunnel_if_set_sa_reply_t *rmp;
+ ipsec_main_t *im = &ipsec_main;
+ vnet_main_t *vnm = im->vnet_main;
+ vnet_sw_interface_t *sw;
+ int rv;
+
+#if WITH_LIBSSL > 0
+ sw = vnet_get_sw_interface (vnm, ntohl (mp->sw_if_index));
+
+ rv = ipsec_set_interface_sa (vnm, sw->hw_if_index, ntohl (mp->sa_id),
+ mp->is_outbound);
+#else
+ clib_warning ("unimplemented");
+#endif
+
+ REPLY_MACRO (VL_API_IPSEC_TUNNEL_IF_SET_SA_REPLY);
+}
+
+
static void
vl_api_ikev2_profile_add_del_t_handler (vl_api_ikev2_profile_add_del_t * mp)
{
}
+int
+ipsec_set_interface_sa (vnet_main_t * vnm, u32 hw_if_index, u32 sa_id,
+ u8 is_outbound)
+{
+ ipsec_main_t *im = &ipsec_main;
+ vnet_hw_interface_t *hi;
+ ipsec_tunnel_if_t *t;
+ ipsec_sa_t *sa, *old_sa;
+ u32 sa_index, old_sa_index;
+ uword *p;
+
+ hi = vnet_get_hw_interface (vnm, hw_if_index);
+ t = pool_elt_at_index (im->tunnel_interfaces, hi->dev_instance);
+
+ sa_index = ipsec_get_sa_index_by_sa_id (sa_id);
+ if (sa_index == ~0)
+ {
+ clib_warning ("SA with ID %u not found", sa_id);
+ return VNET_API_ERROR_INVALID_VALUE;
+ }
+
+ if (ipsec_is_sa_used (sa_index))
+ {
+ clib_warning ("SA with ID %u is already in use", sa_id);
+ return VNET_API_ERROR_INVALID_VALUE;
+ }
+
+ sa = pool_elt_at_index (im->sad, sa_index);
+ if (sa->is_tunnel_ip6)
+ {
+ clib_warning ("IPsec interface not supported with IPv6 endpoints");
+ return VNET_API_ERROR_UNIMPLEMENTED;
+ }
+
+ if (!is_outbound)
+ {
+ u64 key;
+
+ old_sa_index = t->input_sa_index;
+ old_sa = pool_elt_at_index (im->sad, old_sa_index);
+
+ /* unset old inbound hash entry. packets should stop arriving */
+ key =
+ (u64) old_sa->tunnel_dst_addr.ip4.as_u32 << 32 | (u64) old_sa->spi;
+ p = hash_get (im->ipsec_if_pool_index_by_key, key);
+ if (p)
+ hash_unset (im->ipsec_if_pool_index_by_key, key);
+
+ /* set new inbound SA, then set new hash entry */
+ t->input_sa_index = sa_index;
+ key = (u64) sa->tunnel_dst_addr.ip4.as_u32 << 32 | (u64) sa->spi;
+ hash_set (im->ipsec_if_pool_index_by_key, key, hi->dev_instance);
+ }
+ else
+ {
+ old_sa_index = t->output_sa_index;
+ old_sa = pool_elt_at_index (im->sad, old_sa_index);
+ t->output_sa_index = sa_index;
+ }
+
+ /* remove sa_id to sa_index mapping on old SA */
+ if (ipsec_get_sa_index_by_sa_id (old_sa->id) == old_sa_index)
+ hash_unset (im->sa_index_by_sa_id, old_sa->id);
+
+ if (im->cb.add_del_sa_sess_cb)
+ {
+ clib_error_t *err;
+
+ err = im->cb.add_del_sa_sess_cb (old_sa_index, 0);
+ if (err)
+ return VNET_API_ERROR_SYSCALL_ERROR_1;
+ }
+
+ pool_put (im->sad, old_sa);
+
+ return 0;
+}
+
+
clib_error_t *
ipsec_tunnel_if_init (vlib_main_t * vm)
{