19 #ifndef __included_ip6_to_ip4_h__ 20 #define __included_ip6_to_ip4_h__ 45 #define frag_id_6to4(id) ((id) ^ ((id) >> 16)) 60 u8 * l4_protocol,
u16 * l4_offset,
u16 * frag_hdr_offset)
62 if (ip6->
protocol == IP_PROTOCOL_IPV6_FRAGMENTATION)
64 *l4_protocol = ((ip6_frag_hdr_t *) (ip6 + 1))->next_hdr;
65 *frag_hdr_offset =
sizeof (*ip6);
66 *l4_offset =
sizeof (*ip6) +
sizeof (ip6_frag_hdr_t);
72 *l4_offset =
sizeof (*ip6);
75 return (buff_len < (*l4_offset + 4)) ||
77 (*l4_offset + 4 -
sizeof (*ip6)));
97 if (
ip6_parse (ip6, buffer_len, &l4_protocol, &l4_offset, &frag_offset))
106 if (l4_protocol == IP_PROTOCOL_TCP || l4_protocol == IP_PROTOCOL_UDP)
112 else if (l4_protocol == IP_PROTOCOL_ICMP6)
114 icmp46_header_t *icmp = (icmp46_header_t *) (l4);
115 if (icmp->type == ICMP6_echo_request)
117 return (sender) ? ((
u16 *) (icmp))[2] : -1;
119 else if (icmp->type == ICMP6_echo_reply)
121 return (sender) ? -1 : ((
u16 *) (icmp))[2];
141 case ICMP6_echo_request:
142 icmp->type = ICMP4_echo_request;
144 case ICMP6_echo_reply:
145 icmp->type = ICMP4_echo_reply;
147 case ICMP6_destination_unreachable:
152 case ICMP6_destination_unreachable_no_route_to_destination:
153 case ICMP6_destination_unreachable_beyond_scope_of_source_address:
154 case ICMP6_destination_unreachable_address_unreachable:
155 icmp->type = ICMP4_destination_unreachable;
157 ICMP4_destination_unreachable_destination_unreachable_host;
159 case ICMP6_destination_unreachable_destination_administratively_prohibited:
161 ICMP4_destination_unreachable;
163 ICMP4_destination_unreachable_communication_administratively_prohibited;
165 case ICMP6_destination_unreachable_port_unreachable:
166 icmp->type = ICMP4_destination_unreachable;
167 icmp->code = ICMP4_destination_unreachable_port_unreachable;
173 case ICMP6_packet_too_big:
176 icmp->type = ICMP4_destination_unreachable;
179 u32 advertised_mtu = clib_net_to_host_u32 (*((
u32 *) (icmp + 1)));
180 advertised_mtu -= 20;
182 ((
u16 *) (icmp))[3] = clib_host_to_net_u16 (advertised_mtu);
186 case ICMP6_time_exceeded:
189 icmp->type = ICMP4_time_exceeded;
192 case ICMP6_parameter_problem:
197 case ICMP6_parameter_problem_erroneous_header_field:
198 icmp->type = ICMP4_parameter_problem;
199 icmp->code = ICMP4_parameter_problem_pointer_indicates_error;
200 u32 pointer = clib_net_to_host_u32 (*((
u32 *) (icmp + 1)));
204 ((
u8 *) (icmp + 1))[0] =
207 case ICMP6_parameter_problem_unrecognized_next_header:
208 icmp->type = ICMP4_destination_unreachable;
209 icmp->code = ICMP4_destination_unreachable_port_unreachable;
211 case ICMP6_parameter_problem_unrecognized_option:
255 icmp46_header_t *icmp;
262 icmp = (icmp46_header_t *) (ip6 + 1);
266 if (ip6->
protocol != IP_PROTOCOL_ICMP6)
275 u16 *inner_L4_checksum, inner_l4_offset, inner_frag_offset,
277 u8 *inner_l4, inner_protocol;
288 if (
ip6_parse (inner_ip6, ip6_pay_len - 8,
289 &inner_protocol, &inner_l4_offset, &inner_frag_offset))
292 inner_l4 =
u8_ptr_add (inner_ip6, inner_l4_offset);
295 if (inner_frag_offset)
297 ip6_frag_hdr_t *inner_frag =
298 (ip6_frag_hdr_t *)
u8_ptr_add (inner_ip6, inner_frag_offset);
299 inner_frag_id =
frag_id_6to4 (inner_frag->identification);
307 if (inner_protocol == IP_PROTOCOL_TCP)
311 else if (inner_protocol == IP_PROTOCOL_UDP)
315 else if (inner_protocol == IP_PROTOCOL_ICMP6)
317 icmp46_header_t *inner_icmp = (icmp46_header_t *) inner_l4;
319 inner_icmp->type = (inner_icmp->type == ICMP6_echo_request) ?
320 ICMP4_echo_request : ICMP4_echo_reply;
321 inner_protocol = IP_PROTOCOL_ICMP;
322 inner_L4_checksum = &inner_icmp->checksum;
334 if ((rv = inner_fn (inner_ip6, inner_ip4, inner_ctx)) != 0)
342 sizeof (*ip4) +
sizeof (*ip6) - inner_l4_offset);
347 inner_ip4->
protocol = inner_protocol;
350 if (inner_ip4->
protocol == IP_PROTOCOL_ICMP)
353 icmp46_header_t *inner_icmp = (icmp46_header_t *) inner_l4;
354 inner_icmp->checksum = 0;
357 clib_net_to_host_u16 (inner_ip4->
length)
358 - sizeof (*inner_ip4));
364 csum = *inner_L4_checksum;
377 icmp = (icmp46_header_t *)
u8_ptr_add (inner_l4, -
sizeof (*ip4) - 8);
387 if ((rv = fn (ip6, ip4, ctx)) != 0)
390 ip4->ip_version_and_header_length =
393 ip4->fragment_id = 0;
394 ip4->flags_and_fragment_offset = 0;
395 ip4->ttl = ip6->hop_limit;
396 ip4->protocol = IP_PROTOCOL_ICMP;
400 NULL) ? sizeof (*ip4) : (2 *
sizeof (*ip4) -
408 clib_net_to_host_u16 (ip4->length) -
428 ip6_frag_hdr_t *frag;
443 frag = (ip6_frag_hdr_t *)
u8_ptr_add (ip6, frag_offset);
451 if ((rv = fn (ip6, ip4, ctx)) != 0)
458 sizeof (*ip4) - l4_offset +
sizeof (*ip6));
461 clib_host_to_net_u16 (frag_offset |
465 (l4_protocol == IP_PROTOCOL_ICMP6) ? IP_PROTOCOL_ICMP : l4_protocol;
502 if (l4_protocol == IP_PROTOCOL_TCP)
505 checksum = &tcp->checksum;
525 ip6_frag_hdr_t *hdr = (ip6_frag_hdr_t *)
u8_ptr_add (ip6, frag_offset);
535 if ((rv = fn (ip6, ip4, ctx)) != 0)
542 sizeof (*ip4) +
sizeof (*ip6) - l4_offset);
550 if (!udp_checksum && l4_protocol == IP_PROTOCOL_UDP)
602 ip6_frag_hdr_t *hdr = (ip6_frag_hdr_t *)
u8_ptr_add (ip6, frag_offset);
612 if ((rv = fn (ip6, ip4, ctx)) != 0)
619 sizeof (*ip4) +
sizeof (*ip6) - l4_offset);
static_always_inline u8 ip6_translate_tos(const ip6_header_t *ip6)
Translate TOS value from IPv6 to IPv4.
static u16 ip6_get_port(ip6_header_t *ip6, u8 sender, u16 buffer_len)
Get TCP/UDP port number or ICMP id from IPv6 packet.
u16 udp_checksum(udp_header_t *uh, u32 udp_len, void *ih, u8 version)
static int icmp6_to_icmp(vlib_buffer_t *p, ip6_to_ip4_set_fn_t fn, void *ctx, ip6_to_ip4_set_fn_t inner_fn, void *inner_ctx)
Translate ICMP6 packet to ICMP4.
#define clib_memcpy_fast(a, b, c)
u16 current_length
Nbytes between current data and the end of this buffer.
struct _tcp_header tcp_header_t
static_always_inline int icmp6_to_icmp_header(icmp46_header_t *icmp, ip6_header_t **inner_ip6)
Convert type and code value from ICMP6 to ICMP4.
#define u8_ptr_add(ptr, index)
#define static_always_inline
static_always_inline int ip6_parse(const ip6_header_t *ip6, u32 buff_len, u8 *l4_protocol, u16 *l4_offset, u16 *frag_hdr_offset)
Parse some useful information from IPv6 header.
static int ip6_to_ip4_tcp_udp(vlib_buffer_t *p, ip6_to_ip4_set_fn_t fn, void *ctx, u8 udp_checksum)
Translate IPv6 UDP/TCP packet to IPv4.
#define ip6_frag_hdr_more(hdr)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
#define IP4_HEADER_FLAG_MORE_FRAGMENTS
static void * ip6_next_header(ip6_header_t *i)
#define ip6_frag_hdr_offset(hdr)
static ip_csum_t ip_csum_sub_even(ip_csum_t c, ip_csum_t x)
static u8 icmp6_to_icmp_updater_pointer_table[]
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
VLIB buffer representation.
#define IP4_VERSION_AND_HEADER_LENGTH_NO_OPTIONS
#define u16_net_add(u, val)
int(* ip6_to_ip4_set_fn_t)(ip6_header_t *ip6, ip4_header_t *ip4, void *ctx)
IPv6 to IPv4 set call back function type.
static ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
static int ip6_to_ip4(vlib_buffer_t *p, ip6_to_ip4_set_fn_t fn, void *ctx)
Translate IPv6 packet to IPv4 (IP header only).
static u16 ip4_header_checksum(ip4_header_t *i)
static u16 ip_csum_fold(ip_csum_t c)
static ip_csum_t ip_csum_add_even(ip_csum_t c, ip_csum_t x)
static int ip6_to_ip4_fragmented(vlib_buffer_t *p, ip6_to_ip4_set_fn_t fn, void *ctx)
Translate IPv6 fragmented packet to IPv4.