+
+
+static void
+snat_ip4_add_del_interface_address_cb (ip4_main_t * im,
+ uword opaque,
+ u32 sw_if_index,
+ ip4_address_t * address,
+ u32 address_length,
+ u32 if_address_index,
+ u32 is_delete)
+{
+ snat_main_t *sm = &snat_main;
+ snat_static_map_resolve_t *rp;
+ u32 *indices_to_delete = 0;
+ int i, j;
+ int rv;
+
+ for (i = 0; i < vec_len(sm->auto_add_sw_if_indices); i++)
+ {
+ if (sw_if_index == sm->auto_add_sw_if_indices[i])
+ {
+ if (!is_delete)
+ {
+ /* Don't trip over lease renewal, static config */
+ for (j = 0; j < vec_len(sm->addresses); j++)
+ if (sm->addresses[j].addr.as_u32 == address->as_u32)
+ return;
+
+ snat_add_address (sm, address);
+ /* Scan static map resolution vector */
+ for (j = 0; j < vec_len (sm->to_resolve); j++)
+ {
+ rp = sm->to_resolve + j;
+ /* On this interface? */
+ if (rp->sw_if_index == sw_if_index)
+ {
+ /* Add the static mapping */
+ rv = snat_add_static_mapping (rp->l_addr,
+ address[0],
+ rp->l_port,
+ rp->e_port,
+ rp->vrf_id,
+ rp->addr_only,
+ ~0 /* sw_if_index */,
+ rp->proto,
+ rp->is_add);
+ if (rv)
+ clib_warning ("snat_add_static_mapping returned %d",
+ rv);
+ vec_add1 (indices_to_delete, j);
+ }
+ }
+ /* If we resolved any of the outstanding static mappings */
+ if (vec_len(indices_to_delete))
+ {
+ /* Delete them */
+ for (j = vec_len(indices_to_delete)-1; j >= 0; j--)
+ vec_delete(sm->to_resolve, 1, j);
+ vec_free(indices_to_delete);
+ }
+ return;
+ }
+ else
+ {
+ (void) snat_del_address(sm, address[0], 1);
+ return;
+ }
+ }
+ }
+}
+
+
+static int snat_add_interface_address (snat_main_t *sm,
+ u32 sw_if_index,
+ int is_del)
+{
+ ip4_main_t * ip4_main = sm->ip4_main;
+ ip4_address_t * first_int_addr;
+ snat_static_map_resolve_t *rp;
+ u32 *indices_to_delete = 0;
+ int i, j;
+
+ first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index,
+ 0 /* just want the address*/);
+
+ for (i = 0; i < vec_len(sm->auto_add_sw_if_indices); i++)
+ {
+ if (sm->auto_add_sw_if_indices[i] == sw_if_index)
+ {
+ if (is_del)
+ {
+ /* if have address remove it */
+ if (first_int_addr)
+ (void) snat_del_address (sm, first_int_addr[0], 1);
+ else
+ {
+ for (j = 0; j < vec_len (sm->to_resolve); j++)
+ {
+ rp = sm->to_resolve + j;
+ if (rp->sw_if_index == sw_if_index)
+ vec_add1 (indices_to_delete, j);
+ }
+ if (vec_len(indices_to_delete))
+ {
+ for (j = vec_len(indices_to_delete)-1; j >= 0; j--)
+ vec_del1(sm->to_resolve, j);
+ vec_free(indices_to_delete);
+ }
+ }
+ vec_del1(sm->auto_add_sw_if_indices, i);
+ }
+ else
+ return VNET_API_ERROR_VALUE_EXIST;
+
+ return 0;
+ }
+ }
+
+ if (is_del)
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+
+ /* add to the auto-address list */
+ vec_add1(sm->auto_add_sw_if_indices, sw_if_index);
+
+ /* If the address is already bound - or static - add it now */
+ if (first_int_addr)
+ snat_add_address (sm, first_int_addr);
+
+ return 0;
+}
+
+static clib_error_t *
+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;
+
+ /* Get a line of input. */
+ if (!unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "%U", unformat_vnet_sw_interface,
+ sm->vnet_main, &sw_if_index))
+ ;
+ else if (unformat (line_input, "del"))
+ is_del = 1;
+ else
+ return clib_error_return (0, "unknown input '%U'",
+ format_unformat_error, line_input);
+ }
+
+ rv = snat_add_interface_address (sm, sw_if_index, is_del);
+
+ switch (rv)
+ {
+ case 0:
+ break;
+
+ default:
+ return clib_error_return (0, "snat_add_interface_address returned %d",
+ rv);
+ }
+ return 0;
+}
+
+VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = {
+ .path = "snat add interface address",
+ .short_help = "snat add interface address <interface> [del]",
+ .function = snat_add_interface_address_command_fn,
+};