ikev2: add option to disable NAT traversal
[vpp.git] / src / plugins / ikev2 / ikev2.c
index ae48b44..ad727a9 100644 (file)
@@ -105,7 +105,7 @@ typedef u32 ikev2_non_esp_marker;
 static_always_inline u16
 ikev2_get_port (ikev2_sa_t * sa)
 {
-  return sa->natt ? IKEV2_PORT_NATT : IKEV2_PORT;
+  return ikev2_natt_active (sa) ? IKEV2_PORT_NATT : IKEV2_PORT;
 }
 
 static_always_inline int
@@ -427,6 +427,7 @@ ikev2_complete_sa_data (ikev2_sa_t * sa, ikev2_sa_t * sai)
   sa->profile_index = sai->profile_index;
   sa->tun_itf = sai->tun_itf;
   sa->is_tun_itf_set = sai->is_tun_itf_set;
+  sa->natt_state = sai->natt_state;
   sa->i_id.data = _(sai->i_id.data);
   sa->r_id.data = _(sai->r_id.data);
   sa->i_auth.method = sai->i_auth.method;
@@ -743,7 +744,8 @@ ikev2_process_sa_init_req (vlib_main_t * vm,
                                                    udp->src_port);
              if (clib_memcmp (src_sha, n->data, vec_len (src_sha)))
                {
-                 sa->natt = 1;
+                 if (sa->natt_state == IKEV2_NATT_ENABLED)
+                   sa->natt_state = IKEV2_NATT_ACTIVE;
                  ikev2_elog_uint (IKEV2_LOG_DEBUG, "ispi %lx initiator"
                                   " behind NAT", sa->ispi);
                }
@@ -756,7 +758,8 @@ ikev2_process_sa_init_req (vlib_main_t * vm,
                                                    udp->dst_port);
              if (clib_memcmp (dst_sha, n->data, vec_len (dst_sha)))
                {
-                 sa->natt = 1;
+                 if (sa->natt_state == IKEV2_NATT_ENABLED)
+                   sa->natt_state = IKEV2_NATT_ACTIVE;
                  ikev2_elog_uint (IKEV2_LOG_DEBUG, "ispi %lx responder"
                                   " (self) behind NAT", sa->ispi);
                }
@@ -869,7 +872,8 @@ ikev2_process_sa_init_resp (vlib_main_t * vm,
                                                    udp->dst_port);
              if (clib_memcmp (dst_sha, n->data, vec_len (dst_sha)))
                {
-                 sa->natt = 1;
+                 if (sa->natt_state == IKEV2_NATT_ENABLED)
+                   sa->natt_state = IKEV2_NATT_ACTIVE;
                  ikev2_elog_uint (IKEV2_LOG_DEBUG, "ispi %lx initiator"
                                   " (self) behind NAT", sa->ispi);
                }
@@ -1924,7 +1928,7 @@ ikev2_create_tunnel_interface (vlib_main_t * vm,
       a.flags |= IPSEC_SA_FLAG_IS_TUNNEL;
       a.flags |= IPSEC_SA_FLAG_UDP_ENCAP;
     }
-  if (sa->natt)
+  if (ikev2_natt_active (sa))
     a.flags |= IPSEC_SA_FLAG_UDP_ENCAP;
   a.is_rekey = is_rekey;
 
@@ -2050,7 +2054,8 @@ ikev2_create_tunnel_interface (vlib_main_t * vm,
          a.salt_remote = child->salt_ei;
          a.salt_local = child->salt_er;
        }
-      a.dst_port = sa->natt ? sa->dst_port : sa->ipsec_over_udp_port;
+      a.dst_port =
+       ikev2_natt_active (sa) ? sa->dst_port : sa->ipsec_over_udp_port;
       a.src_port = sa->ipsec_over_udp_port;
     }
 
@@ -3197,7 +3202,7 @@ ikev2_node_internal (vlib_main_t * vm,
                clib_net_to_host_u16 (ikev2_get_port (sa0));
 
              if (udp0->dst_port == clib_net_to_host_u16 (IKEV2_PORT_NATT)
-                 && sa0->natt)
+                 && ikev2_natt_active (sa0))
                {
                  if (!has_non_esp_marker)
                    slen = ikev2_insert_non_esp_marker (ike0, slen);
@@ -3635,7 +3640,7 @@ ikev2_initiate_delete_ike_sa_internal (vlib_main_t * vm,
       if (~0 == len)
        return;
 
-      if (sa->natt)
+      if (ikev2_natt_active (sa))
        len = ikev2_insert_non_esp_marker (ike0, len);
 
       if (sa->is_initiator)
@@ -4153,6 +4158,8 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
   sa.state = IKEV2_STATE_SA_INIT;
   sa.tun_itf = p->tun_itf;
   sa.udp_encap = p->udp_encap;
+  if (p->natt_disabled)
+    sa.natt_state = IKEV2_NATT_DISABLED;
   sa.ipsec_over_udp_port = p->ipsec_over_udp_port;
   sa.is_tun_itf_set = 1;
   sa.initial_contact = 1;
@@ -4292,7 +4299,7 @@ ikev2_delete_child_sa_internal (vlib_main_t * vm, ikev2_sa_t * sa,
   if (~0 == len)
     return;
 
-  if (sa->natt)
+  if (ikev2_natt_active (sa))
     len = ikev2_insert_non_esp_marker (ike0, len);
   ikev2_send_ike (vm, &sa->iaddr, &sa->raddr, bi0, len,
                  ikev2_get_port (sa), sa->dst_port, sa->sw_if_index);
@@ -4417,7 +4424,7 @@ ikev2_rekey_child_sa_internal (vlib_main_t * vm, ikev2_sa_t * sa,
   if (~0 == len)
     return;
 
-  if (sa->natt)
+  if (ikev2_natt_active (sa))
     len = ikev2_insert_non_esp_marker (ike0, len);
   ikev2_send_ike (vm, &sa->iaddr, &sa->raddr, bi0, len,
                  ikev2_get_port (sa), ikev2_get_port (sa), sa->sw_if_index);
@@ -4720,6 +4727,17 @@ ikev2_set_liveness_params (u32 period, u32 max_retries)
   return 0;
 }
 
+clib_error_t *
+ikev2_profile_natt_disable (u8 * name)
+{
+  ikev2_profile_t *p = ikev2_profile_index_by_name (name);
+  if (!p)
+    return clib_error_return (0, "unknown profile %v", name);
+
+  p->natt_disabled = 1;
+  return 0;
+}
+
 static void
 ikev2_mngr_process_ipsec_sa (ipsec_sa_t * ipsec_sa)
 {
@@ -4857,7 +4875,7 @@ ikev2_send_informational_request (ikev2_sa_t * sa)
   if (~0 == len)
     return;
 
-  if (sa->natt)
+  if (ikev2_natt_active (sa))
     len = ikev2_insert_non_esp_marker (ike0, len);
 
   if (sa->is_initiator)