diff options
Diffstat (limited to 'src/vnet/ipsec/ipsec_if.c')
-rw-r--r-- | src/vnet/ipsec/ipsec_if.c | 147 |
1 files changed, 71 insertions, 76 deletions
diff --git a/src/vnet/ipsec/ipsec_if.c b/src/vnet/ipsec/ipsec_if.c index 0dfb6909e42..357d638d38b 100644 --- a/src/vnet/ipsec/ipsec_if.c +++ b/src/vnet/ipsec/ipsec_if.c @@ -250,6 +250,18 @@ ipsec_add_del_tunnel_if (ipsec_add_del_tunnel_args_t * args) return 0; } +static u32 +ipsec_tun_mk_input_sa_id (u32 ti) +{ + return (0x80000000 | ti); +} + +static u32 +ipsec_tun_mk_output_sa_id (u32 ti) +{ + return (0xc0000000 | ti); +} + int ipsec_add_del_tunnel_if_internal (vnet_main_t * vnm, ipsec_add_del_tunnel_args_t * args, @@ -260,12 +272,13 @@ ipsec_add_del_tunnel_if_internal (vnet_main_t * vnm, vnet_hw_interface_t *hi = NULL; u32 hw_if_index = ~0; uword *p; - ipsec_sa_t *sa; u32 dev_instance; u32 slot; - u32 tx_fib_index = ~0; + ipsec_key_t crypto_key, integ_key; + ipsec_sa_flags_t flags; + int rv; - u64 key = (u64) args->remote_ip.as_u32 << 32 | (u64) args->remote_spi; + u64 key = (u64) args->remote_ip.ip4.as_u32 << 32 | (u64) args->remote_spi; p = hash_get (im->ipsec_if_pool_index_by_key, key); if (args->is_add) @@ -274,10 +287,6 @@ ipsec_add_del_tunnel_if_internal (vnet_main_t * vnm, if (p) return VNET_API_ERROR_INVALID_VALUE; - tx_fib_index = fib_table_find (FIB_PROTOCOL_IP4, args->tx_table_id); - if (tx_fib_index == ~((u32) 0)) - return VNET_API_ERROR_NO_SUCH_FIB; - pool_get_aligned (im->tunnel_interfaces, t, CLIB_CACHE_LINE_BYTES); clib_memset (t, 0, sizeof (*t)); @@ -296,59 +305,53 @@ ipsec_add_del_tunnel_if_internal (vnet_main_t * vnm, hash_set (im->ipsec_if_real_dev_by_show_dev, t->show_instance, dev_instance); - pool_get (im->sad, sa); - clib_memset (sa, 0, sizeof (*sa)); - t->input_sa_index = sa - im->sad; - sa->protocol = IPSEC_PROTOCOL_ESP; - sa->spi = args->remote_spi; - sa->tunnel_src_addr.ip4.as_u32 = args->remote_ip.as_u32; - sa->tunnel_dst_addr.ip4.as_u32 = args->local_ip.as_u32; - sa->is_tunnel = 1; - sa->use_esn = args->esn; - sa->use_anti_replay = args->anti_replay; - sa->integ_alg = args->integ_alg; - sa->udp_encap = args->udp_encap; - sa->tx_fib_index = ~((u32) 0); /* Not used, but set for troubleshooting */ - if (args->remote_integ_key_len <= sizeof (args->remote_integ_key)) - { - sa->integ_key_len = args->remote_integ_key_len; - clib_memcpy (sa->integ_key, args->remote_integ_key, - args->remote_integ_key_len); - } - sa->crypto_alg = args->crypto_alg; - if (args->remote_crypto_key_len <= sizeof (args->remote_crypto_key)) - { - sa->crypto_key_len = args->remote_crypto_key_len; - clib_memcpy (sa->crypto_key, args->remote_crypto_key, - args->remote_crypto_key_len); - } - - pool_get (im->sad, sa); - clib_memset (sa, 0, sizeof (*sa)); - t->output_sa_index = sa - im->sad; - sa->protocol = IPSEC_PROTOCOL_ESP; - sa->spi = args->local_spi; - sa->tunnel_src_addr.ip4.as_u32 = args->local_ip.as_u32; - sa->tunnel_dst_addr.ip4.as_u32 = args->remote_ip.as_u32; - sa->is_tunnel = 1; - sa->use_esn = args->esn; - sa->use_anti_replay = args->anti_replay; - sa->integ_alg = args->integ_alg; - sa->udp_encap = args->udp_encap; - sa->tx_fib_index = tx_fib_index; - if (args->local_integ_key_len <= sizeof (args->local_integ_key)) - { - sa->integ_key_len = args->local_integ_key_len; - clib_memcpy (sa->integ_key, args->local_integ_key, - args->local_integ_key_len); - } - sa->crypto_alg = args->crypto_alg; - if (args->local_crypto_key_len <= sizeof (args->local_crypto_key)) - { - sa->crypto_key_len = args->local_crypto_key_len; - clib_memcpy (sa->crypto_key, args->local_crypto_key, - args->local_crypto_key_len); - } + flags = IPSEC_SA_FLAG_IS_TUNNEL; + if (args->udp_encap) + flags |= IPSEC_SA_FLAG_UDP_ENCAP; + if (args->esn) + flags |= IPSEC_SA_FLAG_USE_EXTENDED_SEQ_NUM; + if (args->anti_replay) + flags |= IPSEC_SA_FLAG_USE_ANTI_REPLAY; + + ipsec_mk_key (&crypto_key, + args->remote_crypto_key, args->remote_crypto_key_len); + ipsec_mk_key (&integ_key, + args->remote_integ_key, args->remote_integ_key_len); + + rv = ipsec_sa_add (ipsec_tun_mk_input_sa_id (dev_instance), + args->remote_spi, + IPSEC_PROTOCOL_ESP, + args->crypto_alg, + &crypto_key, + args->integ_alg, + &integ_key, + flags, + args->tx_table_id, + &args->remote_ip, + &args->local_ip, &t->input_sa_index); + + if (rv) + return VNET_API_ERROR_UNIMPLEMENTED; + + ipsec_mk_key (&crypto_key, + args->local_crypto_key, args->local_crypto_key_len); + ipsec_mk_key (&integ_key, + args->local_integ_key, args->local_integ_key_len); + + rv = ipsec_sa_add (ipsec_tun_mk_output_sa_id (dev_instance), + args->local_spi, + IPSEC_PROTOCOL_ESP, + args->crypto_alg, + &crypto_key, + args->integ_alg, + &integ_key, + flags, + args->tx_table_id, + &args->local_ip, + &args->remote_ip, &t->output_sa_index); + + if (rv) + return VNET_API_ERROR_UNIMPLEMENTED; hash_set (im->ipsec_if_pool_index_by_key, key, t - im->tunnel_interfaces); @@ -392,18 +395,14 @@ ipsec_add_del_tunnel_if_internal (vnet_main_t * vnm, vnet_delete_hw_interface (vnm, t->hw_if_index); - /* delete input and output SA */ - - sa = pool_elt_at_index (im->sad, t->input_sa_index); - pool_put (im->sad, sa); - - sa = pool_elt_at_index (im->sad, t->output_sa_index); - pool_put (im->sad, sa); - hash_unset (im->ipsec_if_pool_index_by_key, key); hash_unset (im->ipsec_if_real_dev_by_show_dev, t->show_instance); pool_put (im->tunnel_interfaces, t); + + /* delete input and output SA */ + ipsec_sa_del (ipsec_tun_mk_input_sa_id (p[0])); + ipsec_sa_del (ipsec_tun_mk_output_sa_id (p[0])); } if (sw_if_index) @@ -493,29 +492,25 @@ ipsec_set_interface_key (vnet_main_t * vnm, u32 hw_if_index, { sa = pool_elt_at_index (im->sad, t->output_sa_index); sa->crypto_alg = alg; - sa->crypto_key_len = vec_len (key); - clib_memcpy (sa->crypto_key, key, vec_len (key)); + ipsec_mk_key (&sa->crypto_key, key, vec_len (key)); } else if (type == IPSEC_IF_SET_KEY_TYPE_LOCAL_INTEG) { sa = pool_elt_at_index (im->sad, t->output_sa_index); sa->integ_alg = alg; - sa->integ_key_len = vec_len (key); - clib_memcpy (sa->integ_key, key, vec_len (key)); + ipsec_mk_key (&sa->integ_key, key, vec_len (key)); } else if (type == IPSEC_IF_SET_KEY_TYPE_REMOTE_CRYPTO) { sa = pool_elt_at_index (im->sad, t->input_sa_index); sa->crypto_alg = alg; - sa->crypto_key_len = vec_len (key); - clib_memcpy (sa->crypto_key, key, vec_len (key)); + ipsec_mk_key (&sa->crypto_key, key, vec_len (key)); } else if (type == IPSEC_IF_SET_KEY_TYPE_REMOTE_INTEG) { sa = pool_elt_at_index (im->sad, t->input_sa_index); sa->integ_alg = alg; - sa->integ_key_len = vec_len (key); - clib_memcpy (sa->integ_key, key, vec_len (key)); + ipsec_mk_key (&sa->integ_key, key, vec_len (key)); } else return VNET_API_ERROR_INVALID_VALUE; |