/* *INDENT-ON* */
+static void
+nat64_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)
+{
+ nat64_main_t *nm = &nat64_main;
+ int i, j;
+
+ for (i = 0; i < vec_len (nm->auto_add_sw_if_indices); i++)
+ {
+ if (sw_if_index == nm->auto_add_sw_if_indices[i])
+ {
+ if (!is_delete)
+ {
+ /* Don't trip over lease renewal, static config */
+ for (j = 0; j < vec_len (nm->addr_pool); j++)
+ if (nm->addr_pool[j].addr.as_u32 == address->as_u32)
+ return;
+
+ (void) nat64_add_del_pool_addr (address, ~0, 1);
+ return;
+ }
+ else
+ {
+ (void) nat64_add_del_pool_addr (address, ~0, 0);
+ return;
+ }
+ }
+ }
+}
+
clib_error_t *
nat64_init (vlib_main_t * vm)
{
nat64_main_t *nm = &nat64_main;
clib_error_t *error = 0;
vlib_thread_main_t *tm = vlib_get_thread_main ();
+ ip4_add_del_interface_address_callback_t cb4;
+ ip4_main_t *im = &ip4_main;
nm->is_disabled = 0;
nm->tcp_est_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
nm->tcp_incoming_syn_timeout = SNAT_TCP_INCOMING_SYN;
+ /* Set up the interface address add/del callback */
+ cb4.function = nat64_ip4_add_del_interface_address_cb;
+ cb4.function_opaque = 0;
+ vec_add1 (im->add_del_interface_address_callbacks, cb4);
+ nm->ip4_main = im;
+
error:
return error;
}
/* *INDENT-OFF* */
pool_foreach (interface, nm->interfaces,
({
- if (interface->is_inside)
+ if (nat_interface_is_inside(interface))
continue;
snat_add_del_addr_to_fib (addr, 32, interface->sw_if_index, is_add);
/* *INDENT-ON* */
}
+int
+nat64_add_interface_address (u32 sw_if_index, int is_add)
+{
+ nat64_main_t *nm = &nat64_main;
+ ip4_main_t *ip4_main = nm->ip4_main;
+ ip4_address_t *first_int_addr;
+ int i;
+
+ first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index, 0);
+
+ for (i = 0; i < vec_len (nm->auto_add_sw_if_indices); i++)
+ {
+ if (nm->auto_add_sw_if_indices[i] == sw_if_index)
+ {
+ if (is_add)
+ return VNET_API_ERROR_VALUE_EXIST;
+ else
+ {
+ /* if have address remove it */
+ if (first_int_addr)
+ (void) nat64_add_del_pool_addr (first_int_addr, ~0, 0);
+
+ vec_del1 (nm->auto_add_sw_if_indices, i);
+ return 0;
+ }
+ }
+ }
+
+ if (!is_add)
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+
+ /* add to the auto-address list */
+ vec_add1 (nm->auto_add_sw_if_indices, sw_if_index);
+
+ /* If the address is already bound - or static - add it now */
+ if (first_int_addr)
+ (void) nat64_add_del_pool_addr (first_int_addr, ~0, 1);
+
+ return 0;
+}
+
int
nat64_add_del_interface (u32 sw_if_index, u8 is_inside, u8 is_add)
{
snat_address_t *ap;
const char *feature_name, *arc_name;
- /* Check if address already exists */
+ /* Check if interface already exists */
/* *INDENT-OFF* */
pool_foreach (i, nm->interfaces,
({
if (is_add)
{
if (interface)
- return VNET_API_ERROR_VALUE_EXIST;
+ goto set_flags;
pool_get (nm->interfaces, interface);
interface->sw_if_index = sw_if_index;
- interface->is_inside = is_inside;
-
+ interface->flags = 0;
+ set_flags:
+ if (is_inside)
+ interface->flags |= NAT_INTERFACE_FLAG_IS_INSIDE;
+ else
+ interface->flags |= NAT_INTERFACE_FLAG_IS_OUTSIDE;
}
else
{
if (!interface)
return VNET_API_ERROR_NO_SUCH_ENTRY;
- pool_put (nm->interfaces, interface);
+ if ((nat_interface_is_inside (interface)
+ && nat_interface_is_outside (interface)))
+ interface->flags &=
+ is_inside ? ~NAT_INTERFACE_FLAG_IS_INSIDE :
+ ~NAT_INTERFACE_FLAG_IS_OUTSIDE;
+ else
+ pool_put (nm->interfaces, interface);
}
if (!is_inside)
if (prefix)
{
- memset (ip6, 0, 16);
- memcpy (ip6, &p->prefix, p->plen);
+ clib_memcpy (ip6, &p->prefix, sizeof (ip6_address_t));
switch (p->plen)
{
case 32:
}
else
{
- memcpy (ip6, well_known_prefix, 16);
+ clib_memcpy (ip6, well_known_prefix, sizeof (ip6_address_t));
ip6->as_u32[3] = ip4->as_u32;
}
}