summaryrefslogtreecommitdiffstats
path: root/src/vnet/ipsec/ipsec.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/ipsec/ipsec.c')
-rw-r--r--src/vnet/ipsec/ipsec.c271
1 files changed, 208 insertions, 63 deletions
diff --git a/src/vnet/ipsec/ipsec.c b/src/vnet/ipsec/ipsec.c
index 6e4c7f1b687..8ebc57956bb 100644
--- a/src/vnet/ipsec/ipsec.c
+++ b/src/vnet/ipsec/ipsec.c
@@ -412,6 +412,28 @@ ipsec_is_sa_used (u32 sa_index)
return 0;
}
+clib_error_t *
+ipsec_call_add_del_callbacks (ipsec_main_t * im, ipsec_sa_t * sa,
+ u32 sa_index, int is_add)
+{
+ ipsec_ah_backend_t *ab;
+ ipsec_esp_backend_t *eb;
+ switch (sa->protocol)
+ {
+ case IPSEC_PROTOCOL_AH:
+ ab = pool_elt_at_index (im->ah_backends, im->ah_current_backend);
+ if (ab->add_del_sa_sess_cb)
+ return ab->add_del_sa_sess_cb (sa_index, is_add);
+ break;
+ case IPSEC_PROTOCOL_ESP:
+ eb = pool_elt_at_index (im->esp_backends, im->esp_current_backend);
+ if (eb->add_del_sa_sess_cb)
+ return eb->add_del_sa_sess_cb (sa_index, is_add);
+ break;
+ }
+ return 0;
+}
+
int
ipsec_add_del_sa (vlib_main_t * vm, ipsec_sa_t * new_sa, int is_add)
{
@@ -439,12 +461,9 @@ ipsec_add_del_sa (vlib_main_t * vm, ipsec_sa_t * new_sa, int is_add)
return VNET_API_ERROR_SYSCALL_ERROR_1; /* sa used in policy */
}
hash_unset (im->sa_index_by_sa_id, sa->id);
- if (im->cb.add_del_sa_sess_cb)
- {
- err = im->cb.add_del_sa_sess_cb (sa_index, 0);
- if (err)
- return VNET_API_ERROR_SYSCALL_ERROR_1;
- }
+ err = ipsec_call_add_del_callbacks (im, sa, sa_index, 0);
+ if (err)
+ return VNET_API_ERROR_SYSCALL_ERROR_1;
pool_put (im->sad, sa);
}
else /* create new SA */
@@ -453,12 +472,9 @@ ipsec_add_del_sa (vlib_main_t * vm, ipsec_sa_t * new_sa, int is_add)
clib_memcpy (sa, new_sa, sizeof (*sa));
sa_index = sa - im->sad;
hash_set (im->sa_index_by_sa_id, sa->id, sa_index);
- if (im->cb.add_del_sa_sess_cb)
- {
- err = im->cb.add_del_sa_sess_cb (sa_index, 1);
- if (err)
- return VNET_API_ERROR_SYSCALL_ERROR_1;
- }
+ err = ipsec_call_add_del_callbacks (im, sa, sa_index, 1);
+ if (err)
+ return VNET_API_ERROR_SYSCALL_ERROR_1;
}
return 0;
}
@@ -497,12 +513,9 @@ ipsec_set_sa_key (vlib_main_t * vm, ipsec_sa_t * sa_update)
if (0 < sa_update->crypto_key_len || 0 < sa_update->integ_key_len)
{
- if (im->cb.add_del_sa_sess_cb)
- {
- err = im->cb.add_del_sa_sess_cb (sa_index, 0);
- if (err)
- return VNET_API_ERROR_SYSCALL_ERROR_1;
- }
+ err = ipsec_call_add_del_callbacks (im, sa, sa_index, 0);
+ if (err)
+ return VNET_API_ERROR_SYSCALL_ERROR_1;
}
return 0;
@@ -536,13 +549,164 @@ ipsec_check_support (ipsec_sa_t * sa)
return 0;
}
+clib_error_t *
+ipsec_add_del_sa_sess_cb (ipsec_main_t * im, u32 sa_index, u8 is_add)
+{
+ ipsec_ah_backend_t *ah =
+ pool_elt_at_index (im->ah_backends, im->ah_current_backend);
+ if (ah->add_del_sa_sess_cb)
+ {
+ clib_error_t *err = ah->add_del_sa_sess_cb (sa_index, is_add);
+ if (err)
+ return err;
+ }
+ ipsec_esp_backend_t *esp =
+ pool_elt_at_index (im->esp_backends, im->esp_current_backend);
+ if (esp->add_del_sa_sess_cb)
+ {
+ clib_error_t *err = esp->add_del_sa_sess_cb (sa_index, is_add);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+clib_error_t *
+ipsec_check_support_cb (ipsec_main_t * im, ipsec_sa_t * sa)
+{
+ clib_error_t *error = 0;
+ ipsec_ah_backend_t *ah =
+ pool_elt_at_index (im->ah_backends, im->ah_current_backend);
+ ASSERT (ah->check_support_cb);
+ error = ah->check_support_cb (sa);
+ if (error)
+ return error;
+ ipsec_esp_backend_t *esp =
+ pool_elt_at_index (im->esp_backends, im->esp_current_backend);
+ ASSERT (esp->check_support_cb);
+ error = esp->check_support_cb (sa);
+ return error;
+}
+
+
+static void
+ipsec_add_node (vlib_main_t * vm, const char *node_name,
+ const char *prev_node_name, u32 * out_node_index,
+ u32 * out_next_index)
+{
+ vlib_node_t *prev_node, *node;
+ prev_node = vlib_get_node_by_name (vm, (u8 *) prev_node_name);
+ ASSERT (prev_node);
+ node = vlib_get_node_by_name (vm, (u8 *) node_name);
+ ASSERT (node);
+ *out_node_index = node->index;
+ *out_next_index = vlib_node_add_next (vm, prev_node->index, node->index);
+}
+
+u32
+ipsec_register_ah_backend (vlib_main_t * vm, ipsec_main_t * im,
+ const char *name,
+ const char *ah4_encrypt_node_name,
+ const char *ah4_decrypt_node_name,
+ const char *ah6_encrypt_node_name,
+ const char *ah6_decrypt_node_name,
+ check_support_cb_t ah_check_support_cb,
+ add_del_sa_sess_cb_t ah_add_del_sa_sess_cb)
+{
+ ipsec_ah_backend_t *b;
+ pool_get (im->ah_backends, b);
+ b->name = format (NULL, "%s", name);
+
+ ipsec_add_node (vm, ah4_encrypt_node_name, "ipsec4-output",
+ &b->ah4_encrypt_node_index, &b->ah4_encrypt_next_index);
+ ipsec_add_node (vm, ah4_decrypt_node_name, "ipsec4-input",
+ &b->ah4_decrypt_node_index, &b->ah4_decrypt_next_index);
+ ipsec_add_node (vm, ah6_encrypt_node_name, "ipsec6-output",
+ &b->ah6_encrypt_node_index, &b->ah6_encrypt_next_index);
+ ipsec_add_node (vm, ah6_decrypt_node_name, "ipsec6-input",
+ &b->ah6_decrypt_node_index, &b->ah6_decrypt_next_index);
+
+ b->check_support_cb = ah_check_support_cb;
+ b->add_del_sa_sess_cb = ah_add_del_sa_sess_cb;
+ return b - im->ah_backends;
+}
+
+u32
+ipsec_register_esp_backend (vlib_main_t * vm, ipsec_main_t * im,
+ const char *name,
+ const char *esp4_encrypt_node_name,
+ const char *esp4_decrypt_node_name,
+ const char *esp6_encrypt_node_name,
+ const char *esp6_decrypt_node_name,
+ check_support_cb_t esp_check_support_cb,
+ add_del_sa_sess_cb_t esp_add_del_sa_sess_cb)
+{
+ ipsec_esp_backend_t *b;
+ pool_get (im->esp_backends, b);
+ b->name = format (NULL, "%s", name);
+
+ ipsec_add_node (vm, esp4_encrypt_node_name, "ipsec4-output",
+ &b->esp4_encrypt_node_index, &b->esp4_encrypt_next_index);
+ ipsec_add_node (vm, esp4_decrypt_node_name, "ipsec4-input",
+ &b->esp4_decrypt_node_index, &b->esp4_decrypt_next_index);
+ ipsec_add_node (vm, esp6_encrypt_node_name, "ipsec6-output",
+ &b->esp6_encrypt_node_index, &b->esp6_encrypt_next_index);
+ ipsec_add_node (vm, esp6_decrypt_node_name, "ipsec6-input",
+ &b->esp6_decrypt_node_index, &b->esp6_decrypt_next_index);
+
+ b->check_support_cb = esp_check_support_cb;
+ b->add_del_sa_sess_cb = esp_add_del_sa_sess_cb;
+ return b - im->esp_backends;
+}
+
+int
+ipsec_select_ah_backend (ipsec_main_t * im, u32 backend_idx)
+{
+ if (pool_elts (im->sad) > 0
+ || pool_is_free_index (im->ah_backends, backend_idx))
+ {
+ return -1;
+ }
+ ipsec_ah_backend_t *b = pool_elt_at_index (im->ah_backends, backend_idx);
+ im->ah_current_backend = backend_idx;
+ im->ah4_encrypt_node_index = b->ah4_encrypt_node_index;
+ im->ah4_decrypt_node_index = b->ah4_decrypt_node_index;
+ im->ah4_encrypt_next_index = b->ah4_encrypt_next_index;
+ im->ah4_decrypt_next_index = b->ah4_decrypt_next_index;
+ im->ah6_encrypt_node_index = b->ah6_encrypt_node_index;
+ im->ah6_decrypt_node_index = b->ah6_decrypt_node_index;
+ im->ah6_encrypt_next_index = b->ah6_encrypt_next_index;
+ im->ah6_decrypt_next_index = b->ah6_decrypt_next_index;
+ return 0;
+}
+
+int
+ipsec_select_esp_backend (ipsec_main_t * im, u32 backend_idx)
+{
+ if (pool_elts (im->sad) > 0
+ || pool_is_free_index (im->esp_backends, backend_idx))
+ {
+ return -1;
+ }
+ ipsec_esp_backend_t *b = pool_elt_at_index (im->esp_backends, backend_idx);
+ im->esp_current_backend = backend_idx;
+ im->esp4_encrypt_node_index = b->esp4_encrypt_node_index;
+ im->esp4_decrypt_node_index = b->esp4_decrypt_node_index;
+ im->esp4_encrypt_next_index = b->esp4_encrypt_next_index;
+ im->esp4_decrypt_next_index = b->esp4_decrypt_next_index;
+ im->esp6_encrypt_node_index = b->esp6_encrypt_node_index;
+ im->esp6_decrypt_node_index = b->esp6_decrypt_node_index;
+ im->esp6_encrypt_next_index = b->esp6_encrypt_next_index;
+ im->esp6_decrypt_next_index = b->esp6_decrypt_next_index;
+ return 0;
+}
+
static clib_error_t *
ipsec_init (vlib_main_t * vm)
{
clib_error_t *error;
ipsec_main_t *im = &ipsec_main;
vlib_thread_main_t *tm = vlib_get_thread_main ();
- vlib_node_t *node;
ipsec_rand_seed ();
@@ -558,53 +722,34 @@ ipsec_init (vlib_main_t * vm)
vec_validate_aligned (im->empty_buffers, tm->n_vlib_mains - 1,
CLIB_CACHE_LINE_BYTES);
- node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
+ vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
ASSERT (node);
im->error_drop_node_index = node->index;
- node = vlib_get_node_by_name (vm, (u8 *) "esp4-encrypt");
- ASSERT (node);
- im->esp4_encrypt_node_index = node->index;
-
- node = vlib_get_node_by_name (vm, (u8 *) "esp4-decrypt");
- ASSERT (node);
- im->esp4_decrypt_node_index = node->index;
-
- node = vlib_get_node_by_name (vm, (u8 *) "ah4-encrypt");
- ASSERT (node);
- im->ah4_encrypt_node_index = node->index;
-
- node = vlib_get_node_by_name (vm, (u8 *) "ah4-decrypt");
- ASSERT (node);
- im->ah4_decrypt_node_index = node->index;
-
- im->esp4_encrypt_next_index = IPSEC_OUTPUT_NEXT_ESP4_ENCRYPT;
- im->esp4_decrypt_next_index = IPSEC_INPUT_NEXT_ESP4_DECRYPT;
- im->ah4_encrypt_next_index = IPSEC_OUTPUT_NEXT_AH4_ENCRYPT;
- im->ah4_decrypt_next_index = IPSEC_INPUT_NEXT_AH4_DECRYPT;
-
- node = vlib_get_node_by_name (vm, (u8 *) "esp6-encrypt");
- ASSERT (node);
- im->esp6_encrypt_node_index = node->index;
-
- node = vlib_get_node_by_name (vm, (u8 *) "esp6-decrypt");
- ASSERT (node);
- im->esp6_decrypt_node_index = node->index;
-
- node = vlib_get_node_by_name (vm, (u8 *) "ah6-encrypt");
- ASSERT (node);
- im->ah6_encrypt_node_index = node->index;
-
- node = vlib_get_node_by_name (vm, (u8 *) "ah6-decrypt");
- ASSERT (node);
- im->ah6_decrypt_node_index = node->index;
-
- im->esp6_encrypt_next_index = IPSEC_OUTPUT_NEXT_ESP6_ENCRYPT;
- im->esp6_decrypt_next_index = IPSEC_INPUT_NEXT_ESP6_DECRYPT;
- im->ah6_encrypt_next_index = IPSEC_OUTPUT_NEXT_AH6_ENCRYPT;
- im->ah6_decrypt_next_index = IPSEC_INPUT_NEXT_AH6_DECRYPT;
-
- im->cb.check_support_cb = ipsec_check_support;
+ u32 idx = ipsec_register_ah_backend (vm, im, "default openssl backend",
+ "ah4-encrypt",
+ "ah4-decrypt",
+ "ah6-encrypt",
+ "ah6-decrypt",
+ ipsec_check_support,
+ NULL);
+
+ im->ah_default_backend = idx;
+ int rv = ipsec_select_ah_backend (im, idx);
+ ASSERT (0 == rv);
+ (void) (rv); // avoid warning
+
+ idx = ipsec_register_esp_backend (vm, im, "default openssl backend",
+ "esp4-encrypt",
+ "esp4-decrypt",
+ "esp6-encrypt",
+ "esp6-decrypt",
+ ipsec_check_support, NULL);
+ im->esp_default_backend = idx;
+
+ rv = ipsec_select_esp_backend (im, idx);
+ ASSERT (0 == rv);
+ (void) (rv); // avoid warning
if ((error = vlib_call_init_function (vm, ipsec_cli_init)))
return error;