nat: fix coverity warning
[vpp.git] / src / plugins / nat / nat44-ed / nat44_ed_cli.c
index cb0fe9e..6f4485c 100644 (file)
@@ -162,8 +162,8 @@ done:
 }
 
 static clib_error_t *
-nat_show_workers_commnad_fn (vlib_main_t * vm, unformat_input_t * input,
-                            vlib_cli_command_t * cmd)
+nat_show_workers_command_fn (vlib_main_t *vm, unformat_input_t *input,
+                            vlib_cli_command_t *cmd)
 {
   snat_main_t *sm = &snat_main;
   u32 *worker;
@@ -419,9 +419,13 @@ add_address_command_fn (vlib_main_t * vm,
   for (i = 0; i < count; i++)
     {
       if (is_add)
-       rv = snat_add_address (sm, &this_addr, vrf_id, twice_nat);
+       {
+         rv = nat44_ed_add_address (&this_addr, vrf_id, twice_nat);
+       }
       else
-       rv = snat_del_address (sm, this_addr, 0, twice_nat);
+       {
+         rv = nat44_ed_del_address (this_addr, 0, twice_nat);
+       }
 
       switch (rv)
        {
@@ -804,21 +808,22 @@ nat44_show_interfaces_command_fn (vlib_main_t * vm, unformat_input_t * input,
   vlib_cli_output (vm, "NAT44 interfaces:");
   pool_foreach (i, sm->interfaces)
    {
-    vlib_cli_output (vm, " %U %s", format_vnet_sw_if_index_name, vnm,
-                     i->sw_if_index,
-                     (nat_interface_is_inside(i) &&
-                      nat_interface_is_outside(i)) ? "in out" :
-                     (nat_interface_is_inside(i) ? "in" : "out"));
+     vlib_cli_output (vm, " %U %s", format_vnet_sw_if_index_name, vnm,
+                     i->sw_if_index,
+                     (nat44_ed_is_interface_inside (i) &&
+                      nat44_ed_is_interface_outside (i)) ?
+                       "in out" :
+                       (nat44_ed_is_interface_inside (i) ? "in" : "out"));
   }
 
   pool_foreach (i, sm->output_feature_interfaces)
    {
-    vlib_cli_output (vm, " %U output-feature %s",
-                     format_vnet_sw_if_index_name, vnm,
-                     i->sw_if_index,
-                     (nat_interface_is_inside(i) &&
-                      nat_interface_is_outside(i)) ? "in out" :
-                     (nat_interface_is_inside(i) ? "in" : "out"));
+     vlib_cli_output (vm, " %U output-feature %s",
+                     format_vnet_sw_if_index_name, vnm, i->sw_if_index,
+                     (nat44_ed_is_interface_inside (i) &&
+                      nat44_ed_is_interface_outside (i)) ?
+                       "in out" :
+                       (nat44_ed_is_interface_inside (i) ? "in" : "out"));
   }
 
   return 0;
@@ -830,18 +835,17 @@ add_static_mapping_command_fn (vlib_main_t * vm,
                               vlib_cli_command_t * cmd)
 {
   unformat_input_t _line_input, *line_input = &_line_input;
-  clib_error_t *error = 0;
-  ip4_address_t l_addr, e_addr, exact_addr;
-  u32 l_port = 0, e_port = 0, vrf_id = ~0;
-  int is_add = 1, addr_only = 1, rv, exact = 0;
-  u32 sw_if_index = ~0;
   vnet_main_t *vnm = vnet_get_main ();
+  clib_error_t *error = 0;
+  int rv;
+
   nat_protocol_t proto = NAT_PROTOCOL_OTHER;
-  u8 proto_set = 0;
-  twice_nat_type_t twice_nat = TWICE_NAT_DISABLED;
-  u8 out2in_only = 0;
+  ip4_address_t l_addr, e_addr, pool_addr;
+  u32 l_port = 0, e_port = 0, vrf_id = ~0;
+  u8 l_port_set = 0, e_port_set = 0;
+  u32 sw_if_index, flags = 0;
+  int is_add = 1;
 
-  /* Get a line of input. */
   if (!unformat_user (input, unformat_line_input, line_input))
     return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT);
 
@@ -849,38 +853,57 @@ add_static_mapping_command_fn (vlib_main_t * vm,
     {
       if (unformat (line_input, "local %U %u", unformat_ip4_address, &l_addr,
                    &l_port))
-       addr_only = 0;
+       {
+         l_port_set = 1;
+       }
       else
        if (unformat (line_input, "local %U", unformat_ip4_address, &l_addr))
        ;
       else if (unformat (line_input, "external %U %u", unformat_ip4_address,
                         &e_addr, &e_port))
-       addr_only = 0;
+       {
+         e_port_set = 1;
+       }
       else if (unformat (line_input, "external %U", unformat_ip4_address,
                         &e_addr))
        ;
       else if (unformat (line_input, "external %U %u",
                         unformat_vnet_sw_interface, vnm, &sw_if_index,
                         &e_port))
-       addr_only = 0;
+       {
+         flags |= NAT_SM_FLAG_SWITCH_ADDRESS;
+         e_port_set = 1;
+       }
       else if (unformat (line_input, "external %U",
                         unformat_vnet_sw_interface, vnm, &sw_if_index))
-       ;
+       {
+         flags |= NAT_SM_FLAG_SWITCH_ADDRESS;
+       }
       else if (unformat (line_input, "exact %U", unformat_ip4_address,
-                        &exact_addr))
-       exact = 1;
+                        &pool_addr))
+       {
+         flags |= NAT_SM_FLAG_EXACT_ADDRESS;
+       }
       else if (unformat (line_input, "vrf %u", &vrf_id))
        ;
       else if (unformat (line_input, "%U", unformat_nat_protocol, &proto))
-       proto_set = 1;
-      else if (unformat (line_input, "twice-nat"))
-       twice_nat = TWICE_NAT;
+       ;
       else if (unformat (line_input, "self-twice-nat"))
-       twice_nat = TWICE_NAT_SELF;
+       {
+         flags |= NAT_SM_FLAG_SELF_TWICE_NAT;
+       }
+      else if (unformat (line_input, "twice-nat"))
+       {
+         flags |= NAT_SM_FLAG_TWICE_NAT;
+       }
       else if (unformat (line_input, "out2in-only"))
-       out2in_only = 1;
+       {
+         flags |= NAT_SM_FLAG_OUT2IN_ONLY;
+       }
       else if (unformat (line_input, "del"))
-       is_add = 0;
+       {
+         is_add = 0;
+       }
       else
        {
          error = clib_error_return (0, "unknown input: '%U'",
@@ -889,32 +912,37 @@ add_static_mapping_command_fn (vlib_main_t * vm,
        }
     }
 
-  if (twice_nat && addr_only)
+  if (l_port_set != e_port_set)
     {
-      error = clib_error_return (0, "twice NAT only for 1:1 NAPT");
+      error = clib_error_return (0, "Either both ports are set or none.");
       goto done;
     }
 
-  if (addr_only)
+  if (!l_port_set)
     {
-      if (proto_set)
-       {
-         error =
-           clib_error_return (0,
-                              "address only mapping doesn't support protocol");
-         goto done;
-       }
+      flags |= NAT_SM_FLAG_ADDR_ONLY;
     }
-  else if (!proto_set)
+  else
     {
-      error = clib_error_return (0, "protocol is required");
-      goto done;
+      l_port = clib_host_to_net_u16 (l_port);
+      e_port = clib_host_to_net_u16 (e_port);
     }
 
-  rv = snat_add_static_mapping (
-    l_addr, e_addr, clib_host_to_net_u16 (l_port),
-    clib_host_to_net_u16 (e_port), vrf_id, addr_only, sw_if_index, proto,
-    is_add, twice_nat, out2in_only, 0, 0, exact_addr, exact);
+  // TODO: specific pool_addr for both pool & twice nat pool ?
+
+  if (is_add)
+    {
+      rv =
+       nat44_ed_add_static_mapping (l_addr, e_addr, l_port, e_port, proto,
+                                    vrf_id, sw_if_index, flags, pool_addr, 0);
+    }
+  else
+    {
+      rv = nat44_ed_del_static_mapping (l_addr, e_addr, l_port, e_port, proto,
+                                       vrf_id, sw_if_index, flags);
+    }
+
+  // TODO: fix returns
 
   switch (rv)
     {
@@ -943,23 +971,22 @@ done:
   return error;
 }
 
+// TODO: either delete this bullshit or update it
 static clib_error_t *
 add_identity_mapping_command_fn (vlib_main_t * vm,
                                 unformat_input_t * input,
                                 vlib_cli_command_t * cmd)
 {
   unformat_input_t _line_input, *line_input = &_line_input;
-  clib_error_t *error = 0;
-  ip4_address_t addr, pool_addr = { 0 };
-  u32 port = 0, vrf_id = ~0;
-  int is_add = 1;
-  int addr_only = 1;
-  u32 sw_if_index = ~0;
   vnet_main_t *vnm = vnet_get_main ();
-  int rv;
-  nat_protocol_t proto;
+  clib_error_t *error = 0;
+
+  int rv, is_add = 1, port_set = 0;
+  u32 sw_if_index, port, flags, vrf_id = ~0;
+  nat_protocol_t proto = NAT_PROTOCOL_OTHER;
+  ip4_address_t addr;
 
-  addr.as_u32 = 0;
+  flags = NAT_SM_FLAG_IDENTITY_NAT;
 
   /* Get a line of input. */
   if (!unformat_user (input, unformat_line_input, line_input))
@@ -971,14 +998,20 @@ add_identity_mapping_command_fn (vlib_main_t * vm,
        ;
       else if (unformat (line_input, "external %U",
                         unformat_vnet_sw_interface, vnm, &sw_if_index))
-       ;
+       {
+         flags |= NAT_SM_FLAG_SWITCH_ADDRESS;
+       }
       else if (unformat (line_input, "vrf %u", &vrf_id))
        ;
       else if (unformat (line_input, "%U %u", unformat_nat_protocol, &proto,
                         &port))
-       addr_only = 0;
+       {
+         port_set = 1;
+       }
       else if (unformat (line_input, "del"))
-       is_add = 0;
+       {
+         is_add = 0;
+       }
       else
        {
          error = clib_error_return (0, "unknown input: '%U'",
@@ -987,9 +1020,28 @@ add_identity_mapping_command_fn (vlib_main_t * vm,
        }
     }
 
-  rv = snat_add_static_mapping (
-    addr, addr, clib_host_to_net_u16 (port), clib_host_to_net_u16 (port),
-    vrf_id, addr_only, sw_if_index, proto, is_add, 0, 0, 0, 1, pool_addr, 0);
+  if (!port_set)
+    {
+      flags |= NAT_SM_FLAG_ADDR_ONLY;
+    }
+  else
+    {
+      port = clib_host_to_net_u16 (port);
+    }
+
+  if (is_add)
+    {
+
+      rv = nat44_ed_add_static_mapping (addr, addr, port, port, proto, vrf_id,
+                                       sw_if_index, flags, addr, 0);
+    }
+  else
+    {
+      rv = nat44_ed_del_static_mapping (addr, addr, port, port, proto, vrf_id,
+                                       sw_if_index, flags);
+    }
+
+  // TODO: fix returns
 
   switch (rv)
     {
@@ -1027,13 +1079,11 @@ add_lb_static_mapping_command_fn (vlib_main_t * vm,
   clib_error_t *error = 0;
   ip4_address_t l_addr, e_addr;
   u32 l_port = 0, e_port = 0, vrf_id = 0, probability = 0, affinity = 0;
-  int is_add = 1;
-  int rv;
-  nat_protocol_t proto;
   u8 proto_set = 0;
+  nat_protocol_t proto;
   nat44_lb_addr_port_t *locals = 0, local;
-  twice_nat_type_t twice_nat = TWICE_NAT_DISABLED;
-  u8 out2in_only = 0;
+  int rv, is_add = 1;
+  u32 flags = 0;
 
   /* Get a line of input. */
   if (!unformat_user (input, unformat_line_input, line_input))
@@ -1066,15 +1116,25 @@ add_lb_static_mapping_command_fn (vlib_main_t * vm,
        ;
       else if (unformat (line_input, "protocol %U", unformat_nat_protocol,
                         &proto))
-       proto_set = 1;
+       {
+         proto_set = 1;
+       }
       else if (unformat (line_input, "twice-nat"))
-       twice_nat = TWICE_NAT;
+       {
+         flags |= NAT_SM_FLAG_TWICE_NAT;
+       }
       else if (unformat (line_input, "self-twice-nat"))
-       twice_nat = TWICE_NAT_SELF;
+       {
+         flags |= NAT_SM_FLAG_SELF_TWICE_NAT;
+       }
       else if (unformat (line_input, "out2in-only"))
-       out2in_only = 1;
+       {
+         flags |= NAT_SM_FLAG_OUT2IN_ONLY;
+       }
       else if (unformat (line_input, "del"))
-       is_add = 0;
+       {
+         is_add = 0;
+       }
       else if (unformat (line_input, "affinity %u", &affinity))
        ;
       else
@@ -1097,9 +1157,15 @@ add_lb_static_mapping_command_fn (vlib_main_t * vm,
       goto done;
     }
 
-  rv = nat44_add_del_lb_static_mapping (e_addr, (u16) e_port, proto, locals,
-                                       is_add, twice_nat, out2in_only, 0,
-                                       affinity);
+  if (is_add)
+    {
+      rv = nat44_ed_add_lb_static_mapping (e_addr, (u16) e_port, proto, locals,
+                                          flags, 0, affinity);
+    }
+  else
+    {
+      rv = nat44_ed_del_lb_static_mapping (e_addr, (u16) e_port, proto, flags);
+    }
 
   switch (rv)
     {
@@ -1180,10 +1246,8 @@ add_lb_backend_command_fn (vlib_main_t * vm,
       goto done;
     }
 
-  rv =
-    nat44_lb_static_mapping_add_del_local (e_addr, (u16) e_port, l_addr,
-                                          l_port, proto, vrf_id, probability,
-                                          is_add);
+  rv = nat44_ed_add_del_lb_static_mapping_local (
+    e_addr, (u16) e_port, l_addr, l_port, proto, vrf_id, probability, is_add);
 
   switch (rv)
     {
@@ -1235,15 +1299,13 @@ snat_add_interface_address_command_fn (vlib_main_t * vm,
                                       unformat_input_t * input,
                                       vlib_cli_command_t * cmd)
 {
-  snat_main_t *sm = &snat_main;
   unformat_input_t _line_input, *line_input = &_line_input;
-  u32 sw_if_index;
-  int rv;
-  int is_del = 0;
+  snat_main_t *sm = &snat_main;
   clib_error_t *error = 0;
+  int rv, is_del = 0;
   u8 twice_nat = 0;
+  u32 sw_if_index;
 
-  /* Get a line of input. */
   if (!unformat_user (input, unformat_line_input, line_input))
     return clib_error_return (0, NAT44_ED_EXPECTED_ARGUMENT);
 
@@ -1253,9 +1315,13 @@ snat_add_interface_address_command_fn (vlib_main_t * vm,
                    sm->vnet_main, &sw_if_index))
        ;
       else if (unformat (line_input, "twice-nat"))
-       twice_nat = 1;
+       {
+         twice_nat = 1;
+       }
       else if (unformat (line_input, "del"))
-       is_del = 1;
+       {
+         is_del = 1;
+       }
       else
        {
          error = clib_error_return (0, "unknown input '%U'",
@@ -1264,17 +1330,21 @@ snat_add_interface_address_command_fn (vlib_main_t * vm,
        }
     }
 
-  rv = snat_add_interface_address (sm, sw_if_index, is_del, twice_nat);
-
-  switch (rv)
+  if (!is_del)
     {
-    case 0:
-      break;
-
-    default:
-      error = clib_error_return (0, "snat_add_interface_address returned %d",
-                                rv);
-      goto done;
+      rv = nat44_ed_add_interface_address (sw_if_index, twice_nat);
+      if (rv)
+       {
+         error = clib_error_return (0, "add address returned %d", rv);
+       }
+    }
+  else
+    {
+      rv = nat44_ed_del_interface_address (sw_if_index, twice_nat);
+      if (rv)
+       {
+         error = clib_error_return (0, "del address returned %d", rv);
+       }
     }
 
 done:
@@ -1316,22 +1386,61 @@ nat44_show_sessions_command_fn (vlib_main_t * vm, unformat_input_t * input,
   clib_error_t *error = 0;
   snat_main_per_thread_data_t *tsm;
   snat_main_t *sm = &snat_main;
-
-  int i = 0;
+  ip4_address_t i2o_sa, i2o_da, o2i_sa, o2i_da;
+  u8 filter_i2o_sa = 0, filter_i2o_da = 0;
+  u8 filter_o2i_sa = 0, filter_o2i_da = 0;
+  u16 i2o_sp, i2o_dp, o2i_sp, o2i_dp;
+  u8 filter_i2o_sp = 0, filter_i2o_dp = 0;
+  u8 filter_o2i_sp = 0, filter_o2i_dp = 0;
+  nat_protocol_t proto;
+  u8 filter_proto = 0;
+  u8 had_input = 1, filtering = 0;
+  int i = 0, showed_sessions;
 
   if (!unformat_user (input, unformat_line_input, line_input))
-    goto print;
+    {
+      had_input = 0;
+      goto print;
+    }
 
   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     {
-      error = clib_error_return (0, "unknown input '%U'",
-                                format_unformat_error, line_input);
-      break;
+      if (unformat (line_input, "filter i2o saddr %U", unformat_ip4_address,
+                   &i2o_sa))
+       filter_i2o_sa = filtering = 1;
+      else if (unformat (line_input, "filter i2o daddr %U",
+                        unformat_ip4_address, &i2o_da))
+       filter_i2o_da = filtering = 1;
+      else if (unformat (line_input, "filter o2i saddr %U",
+                        unformat_ip4_address, &o2i_sa))
+       filter_o2i_sa = filtering = 1;
+      else if (unformat (line_input, "filter o2i daddr %U",
+                        unformat_ip4_address, &o2i_da))
+       filter_o2i_da = filtering = 1;
+      else if (unformat (line_input, "filter i2o sport %u", &i2o_sp))
+       filter_i2o_sp = filtering = 1;
+      else if (unformat (line_input, "filter i2o dport %u", &i2o_dp))
+       filter_i2o_dp = filtering = 1;
+      else if (unformat (line_input, "filter o2i sport %u", &o2i_sp))
+       filter_o2i_sp = filtering = 1;
+      else if (unformat (line_input, "filter o2i dport %u", &o2i_dp))
+       filter_o2i_dp = filtering = 1;
+      else if (unformat (line_input, "filter i2o proto %U",
+                        unformat_nat_protocol, &proto))
+       filter_proto = filtering = 1;
+      else if (unformat (line_input, "filter o2i proto %U",
+                        unformat_nat_protocol, &proto))
+       filter_proto = filtering = 1;
+      else
+       {
+         error = clib_error_return (0, "unknown input '%U'",
+                                    format_unformat_error, line_input);
+         goto done;
+       }
     }
-  unformat_free (line_input);
 
 print:
-    vlib_cli_output (vm, "NAT44 ED sessions:");
+  vlib_cli_output (vm, "NAT44 ED sessions:");
 
   vec_foreach_index (i, sm->per_thread_data)
     {
@@ -1341,12 +1450,52 @@ print:
                        i, vlib_worker_threads[i].name,
                        pool_elts (tsm->sessions));
 
-          snat_session_t *s;
-          pool_foreach (s, tsm->sessions)
-           {
-            vlib_cli_output (vm, "  %U\n", format_snat_session, tsm, s);
-          }
+      showed_sessions = 0;
+      snat_session_t *s;
+      pool_foreach (s, tsm->sessions)
+       {
+         if (filtering)
+           {
+             if (filter_i2o_sa && i2o_sa.as_u32 != s->i2o.match.saddr.as_u32)
+               continue;
+             if (filter_i2o_da && i2o_da.as_u32 != s->i2o.match.daddr.as_u32)
+               continue;
+             if (filter_o2i_sa && o2i_sa.as_u32 != s->o2i.match.saddr.as_u32)
+               continue;
+             if (filter_o2i_da && o2i_da.as_u32 != s->o2i.match.daddr.as_u32)
+               continue;
+             if (filter_i2o_sp &&
+                 i2o_sp != clib_net_to_host_u16 (s->i2o.match.sport))
+               continue;
+             if (filter_i2o_dp &&
+                 i2o_dp != clib_net_to_host_u16 (s->i2o.match.dport))
+               continue;
+             if (filter_o2i_sp &&
+                 o2i_sp != clib_net_to_host_u16 (s->o2i.match.sport))
+               continue;
+             if (filter_o2i_dp &&
+                 o2i_dp != clib_net_to_host_u16 (s->o2i.match.dport))
+               continue;
+             if (filter_proto && proto != s->nat_proto)
+               continue;
+             showed_sessions++;
+           }
+         vlib_cli_output (vm, "  %U\n", format_snat_session, tsm, s);
+       }
+      if (filtering)
+       {
+         vlib_cli_output (vm,
+                          "Showed: %d, Filtered: %d of total %d "
+                          "sessions of thread %d\n\n",
+                          showed_sessions,
+                          pool_elts (tsm->sessions) - showed_sessions,
+                          pool_elts (tsm->sessions), i);
+       }
     }
+
+done:
+  if (had_input)
+    unformat_free (line_input);
   return error;
 }
 
@@ -1434,10 +1583,9 @@ nat44_del_session_command_fn (vlib_main_t * vm,
        }
     }
 
-    rv =
-      nat44_del_ed_session (sm, &addr, clib_host_to_net_u16 (port), &eh_addr,
-                           clib_host_to_net_u16 (eh_port),
-                           nat_proto_to_ip_proto (proto), vrf_id, is_in);
+  rv = nat44_ed_del_session (sm, &addr, clib_host_to_net_u16 (port), &eh_addr,
+                            clib_host_to_net_u16 (eh_port),
+                            nat_proto_to_ip_proto (proto), vrf_id, is_in);
 
   switch (rv)
     {
@@ -1632,7 +1780,7 @@ VLIB_CLI_COMMAND (set_workers_command, static) = {
 VLIB_CLI_COMMAND (nat_show_workers_command, static) = {
   .path = "show nat workers",
   .short_help = "show nat workers",
-  .function = nat_show_workers_commnad_fn,
+  .function = nat_show_workers_command_fn,
 };
 
 /*?
@@ -1990,7 +2138,9 @@ VLIB_CLI_COMMAND (nat44_show_interface_address_command, static) = {
 ?*/
 VLIB_CLI_COMMAND (nat44_show_sessions_command, static) = {
   .path = "show nat44 sessions",
-  .short_help = "show nat44 sessions",
+  .short_help = "show nat44 sessions [filter {i2o | o2i} {saddr <ip4-addr> "
+               "| sport <n> | daddr <ip4-addr> | dport <n> | proto <proto>} "
+               "[filter .. [..]]]",
   .function = nat44_show_sessions_command_fn,
 };