#include <vnet/ip/ip4_to_ip6.h>
#include <vnet/fib/ip4_fib.h>
-/* *INDENT-OFF* */
-static u8 well_known_prefix[] = {
- 0x00, 0x64, 0xff, 0x9b,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
-/* *INDENT-ON* */
typedef struct
{
u32 sw_if_index;
ip46_address_t saddr, daddr;
ip6_address_t ip6_saddr;
udp_header_t *udp = ip4_next_header (ip4);
+ tcp_header_t *tcp = ip4_next_header (ip4);
snat_protocol_t proto = ip_proto_to_snat_proto (ip4->protocol);
u16 dport = udp->dst_port;
u16 sport = udp->src_port;
u32 sw_if_index, fib_index;
+ u16 *checksum;
+ ip_csum_t csum;
sw_if_index = vnet_buffer (ctx->b)->sw_if_index[VLIB_RX];
fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index);
memset (&daddr, 0, sizeof (daddr));
daddr.ip4.as_u32 = ip4->dst_address.as_u32;
- memcpy (&ip6_saddr, well_known_prefix, sizeof (ip6_saddr));
- ip6_saddr.as_u32[3] = ip4->src_address.as_u32;
-
ste =
nat64_db_st_entry_find (&nm->db, &daddr, &saddr, dport, sport, proto,
fib_index, 0);
if (!bibe)
return -1;
+ nat64_compose_ip6 (&ip6_saddr, &ip4->src_address, bibe->fib_index);
ste =
nat64_db_st_entry_create (&nm->db, bibe, &ip6_saddr, &saddr.ip4,
sport);
nat64_session_reset_timeout (ste, ctx->vm);
- ip6->src_address.as_u64[0] = ip6_saddr.as_u64[0];
- ip6->src_address.as_u64[1] = ip6_saddr.as_u64[1];
+ ip6->src_address.as_u64[0] = ste->in_r_addr.as_u64[0];
+ ip6->src_address.as_u64[1] = ste->in_r_addr.as_u64[1];
ip6->dst_address.as_u64[0] = bibe->in_addr.as_u64[0];
ip6->dst_address.as_u64[1] = bibe->in_addr.as_u64[1];
udp->dst_port = bibe->in_port;
+ if (proto == SNAT_PROTOCOL_UDP)
+ checksum = &udp->checksum;
+ else
+ checksum = &tcp->checksum;
+ csum = ip_csum_sub_even (*checksum, dport);
+ csum = ip_csum_add_even (csum, udp->dst_port);
+ *checksum = ip_csum_fold (csum);
+
+ vnet_buffer (ctx->b)->sw_if_index[VLIB_TX] = bibe->fib_index;
+
return 0;
}
memset (&daddr, 0, sizeof (daddr));
daddr.ip4.as_u32 = ip4->dst_address.as_u32;
- memcpy (&ip6_saddr, well_known_prefix, sizeof (ip6_saddr));
- ip6_saddr.as_u32[3] = ip4->src_address.as_u32;
-
if (icmp->type == ICMP6_echo_request || icmp->type == ICMP6_echo_reply)
{
u16 out_id = ((u16 *) (icmp))[2];
if (!bibe)
return -1;
+ nat64_compose_ip6 (&ip6_saddr, &ip4->src_address, bibe->fib_index);
ste =
nat64_db_st_entry_create (&nm->db, bibe, &ip6_saddr, &saddr.ip4,
0);
nat64_session_reset_timeout (ste, ctx->vm);
- ip6->src_address.as_u64[0] = ip6_saddr.as_u64[0];
- ip6->src_address.as_u64[1] = ip6_saddr.as_u64[1];
+ ip6->src_address.as_u64[0] = ste->in_r_addr.as_u64[0];
+ ip6->src_address.as_u64[1] = ste->in_r_addr.as_u64[1];
ip6->dst_address.as_u64[0] = bibe->in_addr.as_u64[0];
ip6->dst_address.as_u64[1] = bibe->in_addr.as_u64[1];
((u16 *) (icmp))[2] = bibe->in_port;
+ vnet_buffer (ctx->b)->sw_if_index[VLIB_TX] = bibe->fib_index;
}
else
{
ip6_header_t *inner_ip6 = (ip6_header_t *) u8_ptr_add (icmp, 8);
- ip6->src_address.as_u64[0] = ip6_saddr.as_u64[0];
- ip6->src_address.as_u64[1] = ip6_saddr.as_u64[1];
+ nat64_compose_ip6 (&ip6->src_address, &ip4->src_address,
+ vnet_buffer (ctx->b)->sw_if_index[VLIB_TX]);
ip6->dst_address.as_u64[0] = inner_ip6->src_address.as_u64[0];
ip6->dst_address.as_u64[1] = inner_ip6->src_address.as_u64[1];
}
nat64_db_bib_entry_t *bibe;
nat64_db_st_entry_t *ste;
ip46_address_t saddr, daddr;
- ip6_address_t ip6_daddr;
u32 sw_if_index, fib_index;
snat_protocol_t proto = ip_proto_to_snat_proto (ip4->protocol);
memset (&daddr, 0, sizeof (daddr));
daddr.ip4.as_u32 = ip4->dst_address.as_u32;
- memcpy (&ip6_daddr, well_known_prefix, sizeof (ip6_daddr));
- ip6_daddr.as_u32[3] = ip4->dst_address.as_u32;
-
if (proto == SNAT_PROTOCOL_ICMP)
{
icmp46_header_t *icmp = ip4_next_header (ip4);
if (!bibe)
return -1;
- ip6->dst_address.as_u64[0] = ip6_daddr.as_u64[0];
- ip6->dst_address.as_u64[1] = ip6_daddr.as_u64[1];
+ ip6->dst_address.as_u64[0] = ste->in_r_addr.as_u64[0];
+ ip6->dst_address.as_u64[1] = ste->in_r_addr.as_u64[1];
ip6->src_address.as_u64[0] = bibe->in_addr.as_u64[0];
ip6->src_address.as_u64[1] = bibe->in_addr.as_u64[1];
((u16 *) (icmp))[2] = bibe->in_port;
+
+ vnet_buffer (ctx->b)->sw_if_index[VLIB_TX] = bibe->fib_index;
}
else
{
udp_header_t *udp = ip4_next_header (ip4);
+ tcp_header_t *tcp = ip4_next_header (ip4);
u16 dport = udp->dst_port;
u16 sport = udp->src_port;
+ u16 *checksum;
+ ip_csum_t csum;
ste =
nat64_db_st_entry_find (&nm->db, &saddr, &daddr, sport, dport, proto,
if (!bibe)
return -1;
- ip6->dst_address.as_u64[0] = ip6_daddr.as_u64[0];
- ip6->dst_address.as_u64[1] = ip6_daddr.as_u64[1];
+ nat64_compose_ip6 (&ip6->dst_address, &daddr.ip4, bibe->fib_index);
ip6->src_address.as_u64[0] = bibe->in_addr.as_u64[0];
ip6->src_address.as_u64[1] = bibe->in_addr.as_u64[1];
udp->src_port = bibe->in_port;
+
+ if (proto == SNAT_PROTOCOL_UDP)
+ checksum = &udp->checksum;
+ else
+ checksum = &tcp->checksum;
+ if (*checksum)
+ {
+ csum = ip_csum_sub_even (*checksum, sport);
+ csum = ip_csum_add_even (csum, udp->src_port);
+ *checksum = ip_csum_fold (csum);
+ }
+
+ vnet_buffer (ctx->b)->sw_if_index[VLIB_TX] = bibe->fib_index;
}
return 0;