- if (local_ip_type != remote_ip_type)
- {
- rv = VNET_API_ERROR_INVALID_VALUE;
- goto done;
- }
-
- flags = IPSEC_SA_FLAG_NONE;
-
- if (mp->udp_encap)
- flags |= IPSEC_SA_FLAG_UDP_ENCAP;
- if (mp->esn)
- flags |= IPSEC_SA_FLAG_USE_ESN;
- if (mp->anti_replay)
- flags |= IPSEC_SA_FLAG_USE_ANTI_REPLAY;
-
- ipsec_mk_key (&crypto_key, mp->remote_crypto_key,
- mp->remote_crypto_key_len);
- ipsec_mk_key (&integ_key, mp->remote_integ_key, mp->remote_integ_key_len);
- ipsec_mk_key (&crypto_key, mp->local_crypto_key, mp->local_crypto_key_len);
- ipsec_mk_key (&integ_key, mp->local_integ_key, mp->local_integ_key_len);
-
- fib_index =
- fib_table_find (fib_proto_from_ip46 (local_ip_type),
- ntohl (mp->tx_table_id));
-
- if (~0 == fib_index)
- {
- rv = VNET_API_ERROR_NO_SUCH_FIB;
- goto done;
- }
-
- if (mp->is_add)
- {
- // remote = input, local = output
- /* create an ip-ip tunnel, then the two SA, then bind them */
- rv = ipip_add_tunnel (transport,
- (mp->renumber ? ntohl (mp->show_instance) : ~0),
- &local_ip,
- &remote_ip, fib_index,
- TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
- TUNNEL_MODE_P2P, &sw_if_index);
-
- if (rv)
- goto done;
-
- rv = ipsec_sa_add_and_lock (ipsec_tun_mk_input_sa_id (sw_if_index),
- ntohl (mp->remote_spi),
- IPSEC_PROTOCOL_ESP,
- mp->crypto_alg,
- &crypto_key,
- mp->integ_alg,
- &integ_key,
- (flags | IPSEC_SA_FLAG_IS_INBOUND),
- ntohl (mp->tx_table_id),
- mp->salt, &remote_ip, &local_ip, NULL);
-
- if (rv)
- goto done;
-
- rv = ipsec_sa_add_and_lock (ipsec_tun_mk_output_sa_id (sw_if_index),
- ntohl (mp->local_spi),
- IPSEC_PROTOCOL_ESP,
- mp->crypto_alg,
- &crypto_key,
- mp->integ_alg,
- &integ_key,
- flags,
- ntohl (mp->tx_table_id),
- mp->salt, &local_ip, &remote_ip, NULL);
-
- if (rv)
- goto done;
-
- rv = ipsec_tun_protect_update_one (sw_if_index, NULL,
- ipsec_tun_mk_output_sa_id
- (sw_if_index),
- ipsec_tun_mk_input_sa_id
- (sw_if_index));
- if (rv)
- goto done;
-
- /* the SAs are locked as a result of being used for proection,
- * they cannot be removed from the API, since they cannot be refered
- * to by the API. unlock them now, so that if the tunnel is rekeyed
- * they-ll disapper
- */
- ipsec_sa_unlock_id (ipsec_tun_mk_input_sa_id (sw_if_index));
- ipsec_sa_unlock_id (ipsec_tun_mk_output_sa_id (sw_if_index));
- }
- else
- {
- /* *INDENT-OFF* */
- ipip_tunnel_key_t key = {
- .transport = transport,
- .fib_index = fib_index,
- .src = local_ip,
- .dst = remote_ip
- };
- /* *INDENT-ON* */
-
- ipip_tunnel_t *t = ipip_tunnel_db_find (&key);
-
- if (NULL != t)
- {
- rv = ipsec_tun_protect_del (t->sw_if_index, NULL);
- ipip_del_tunnel (t->sw_if_index);
- }
- else
- rv = VNET_API_ERROR_NO_SUCH_ENTRY;
- }
-
-#else
- rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-done: