diff options
Diffstat (limited to 'src/plugins/nat/nat44-ed/nat44_ed.c')
-rw-r--r-- | src/plugins/nat/nat44-ed/nat44_ed.c | 153 |
1 files changed, 146 insertions, 7 deletions
diff --git a/src/plugins/nat/nat44-ed/nat44_ed.c b/src/plugins/nat/nat44-ed/nat44_ed.c index 56c5ab2e32f..7907d8ffa6b 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed.c +++ b/src/plugins/nat/nat44-ed/nat44_ed.c @@ -309,6 +309,112 @@ is_snat_address_used_in_static_mapping (snat_main_t *sm, ip4_address_t addr) return 0; } +static ip_interface_address_t * +nat44_ed_get_ip_interface_address (u32 sw_if_index, ip4_address_t addr) +{ + snat_main_t *sm = &snat_main; + + ip_lookup_main_t *lm = &sm->ip4_main->lookup_main; + ip_interface_address_t *ia; + ip4_address_t *ip4a; + + foreach_ip_interface_address ( + lm, ia, sw_if_index, 1, ({ + ip4a = ip_interface_address_get_address (lm, ia); + nat_log_debug ("sw_if_idx: %u addr: %U ? %U", sw_if_index, + format_ip4_address, ip4a, format_ip4_address, &addr); + if (ip4a->as_u32 == addr.as_u32) + { + return ia; + } + })); + return NULL; +} + +static int +nat44_ed_resolve_nat_addr_len (snat_address_t *ap, + snat_interface_t *interfaces) +{ + ip_interface_address_t *ia; + snat_interface_t *i; + u32 fib_index; + + pool_foreach (i, interfaces) + { + if (!nat44_ed_is_interface_outside (i)) + { + continue; + } + + fib_index = ip4_fib_table_get_index_for_sw_if_index (i->sw_if_index); + if (fib_index != ap->fib_index) + { + continue; + } + + if ((ia = nat44_ed_get_ip_interface_address (i->sw_if_index, ap->addr))) + { + ap->addr_len = ia->address_length; + ap->sw_if_index = i->sw_if_index; + ap->net.as_u32 = (ap->addr.as_u32 >> (32 - ap->addr_len)) + << (32 - ap->addr_len); + + nat_log_debug ("pool addr %U binds to -> sw_if_idx: %u net: %U/%u", + format_ip4_address, &ap->addr, ap->sw_if_index, + format_ip4_address, &ap->net, ap->addr_len); + return 0; + } + } + return 1; +} + +static void +nat44_ed_update_outside_if_addresses (snat_address_t *ap) +{ + snat_main_t *sm = &snat_main; + + if (!nat44_ed_resolve_nat_addr_len (ap, sm->interfaces)) + { + return; + } + + if (!nat44_ed_resolve_nat_addr_len (ap, sm->output_feature_interfaces)) + { + return; + } +} + +static void +nat44_ed_bind_if_addr_to_nat_addr (u32 sw_if_index) +{ + snat_main_t *sm = &snat_main; + ip_interface_address_t *ia; + snat_address_t *ap; + + u32 fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index); + + vec_foreach (ap, sm->addresses) + { + if (fib_index != ap->fib_index) + { + continue; + } + + if ((ia = nat44_ed_get_ip_interface_address (sw_if_index, ap->addr))) + { + ap->addr_len = ia->address_length; + ap->sw_if_index = sw_if_index; + ap->net.as_u32 = (ap->addr.as_u32 >> (32 - ap->addr_len)) + << (32 - ap->addr_len); + + nat_log_debug ("pool addr %U binds to -> sw_if_idx: %u net: %U/%u", + format_ip4_address, &ap->addr, ap->sw_if_index, + format_ip4_address, &ap->net, ap->addr_len); + return; + } + } +} + static void nat44_ed_add_del_addr_to_fib (ip4_address_t *addr, u8 p_len, u32 sw_if_index, int is_add) @@ -424,6 +530,7 @@ nat44_ed_add_address (ip4_address_t *addr, u32 vrf_id, u8 twice_nat) vec_add2 (sm->addresses, ap, 1); } + ap->addr_len = ~0; ap->fib_index = ~0; ap->addr = *addr; @@ -433,12 +540,13 @@ nat44_ed_add_address (ip4_address_t *addr, u32 vrf_id, u8 twice_nat) FIB_PROTOCOL_IP4, vrf_id, sm->fib_src_low); } - if (!twice_nat) - { - // if we don't have enabled interface we don't add address - // to fib - nat44_ed_add_del_addr_to_fib_foreach_out_if (addr, 1); - } + if (!twice_nat) + { + // if we don't have enabled interface we don't add address + // to fib + nat44_ed_add_del_addr_to_fib_foreach_out_if (addr, 1); + nat44_ed_update_outside_if_addresses (ap); + } return 0; } @@ -1641,6 +1749,8 @@ nat44_ed_add_interface (u32 sw_if_index, u8 is_inside) nat44_ed_add_del_addr_to_fib_foreach_addr (sw_if_index, 1); nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 1); + + nat44_ed_bind_if_addr_to_nat_addr (sw_if_index); } else { @@ -1850,6 +1960,8 @@ nat44_ed_add_output_interface (u32 sw_if_index) nat44_ed_add_del_addr_to_fib_foreach_addr (sw_if_index, 1); nat44_ed_add_del_addr_to_fib_foreach_addr_only_sm (sw_if_index, 1); + nat44_ed_bind_if_addr_to_nat_addr (sw_if_index); + return 0; } @@ -3244,7 +3356,7 @@ nat44_ed_add_del_interface_address_cb (ip4_main_t *im, uword opaque, { snat_main_t *sm = &snat_main; snat_static_map_resolve_t *rp; - snat_address_t *addresses = sm->addresses; + snat_address_t *ap, *addresses = sm->addresses; u8 twice_nat = 0; int rv, i; @@ -3259,6 +3371,33 @@ nat44_ed_add_del_interface_address_cb (ip4_main_t *im, uword opaque, if (!is_sw_if_index_reg_for_auto_resolve ( sm->auto_add_sw_if_indices_twice_nat, sw_if_index)) { + // interface resolve + u32 fib_index = + ip4_fib_table_get_index_for_sw_if_index (sw_if_index); + vec_foreach (ap, sm->addresses) + { + if ((fib_index == ap->fib_index) && + (address->as_u32 == ap->addr.as_u32)) + { + if (!is_delete) + { + ap->addr_len = address_length; + ap->sw_if_index = sw_if_index; + ap->net.as_u32 = (ap->addr.as_u32 >> (32 - ap->addr_len)) + << (32 - ap->addr_len); + + nat_log_debug ( + "pool addr %U binds to -> sw_if_idx: %u net: %U/%u", + format_ip4_address, &ap->addr, ap->sw_if_index, + format_ip4_address, &ap->net, ap->addr_len); + } + else + { + ap->addr_len = ~0; + } + break; + } + } return; } else |