diff options
Diffstat (limited to 'src/vnet/ipsec/ipsec.c')
-rw-r--r-- | src/vnet/ipsec/ipsec.c | 271 |
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; |