19 #ifndef __included_ip6_to_ip4_h__ 20 #define __included_ip6_to_ip4_h__ 49 #define frag_id_6to4(id) ((id) ^ ((id) >> 16)) 66 u32 buff_len,
u8 * l4_protocol,
u16 * l4_offset,
67 u16 * frag_hdr_offset)
69 ip6_ext_header_t *last_hdr, *frag_hdr;
72 (vm, b, ip6, IP_PROTOCOL_IPV6_FRAGMENTATION, &length, &frag_hdr,
82 *frag_hdr_offset = (
u8 *) frag_hdr - (
u8 *)
ip6;
88 *l4_protocol = last_hdr->next_hdr;
95 *l4_offset =
sizeof (*ip6) + length;
97 return (buff_len < (*l4_offset + 4)) ||
99 (*l4_offset + 4 -
sizeof (*ip6)));
120 u32 * tcp_ack_number,
u32 * tcp_seq_number)
128 (vm, b, ip6, buffer_len, &l4_protocol, &l4_offset, &frag_offset))
138 *ip_protocol = l4_protocol;
141 if (l4_protocol == IP_PROTOCOL_TCP || l4_protocol == IP_PROTOCOL_UDP)
147 if (icmp_type_or_tcp_flags && l4_protocol == IP_PROTOCOL_TCP)
149 if (tcp_ack_number && l4_protocol == IP_PROTOCOL_TCP)
151 if (tcp_seq_number && l4_protocol == IP_PROTOCOL_TCP)
154 else if (l4_protocol == IP_PROTOCOL_ICMP6)
156 icmp46_header_t *icmp = (icmp46_header_t *) (l4);
157 if (icmp_type_or_tcp_flags)
158 *icmp_type_or_tcp_flags = ((icmp46_header_t *) (l4))->
type;
159 if (icmp->type == ICMP6_echo_request)
162 *src_port = ((
u16 *) (icmp))[2];
164 *dst_port = ((
u16 *) (icmp))[2];
166 else if (icmp->type == ICMP6_echo_reply)
169 *src_port = ((
u16 *) (icmp))[2];
171 *dst_port = ((
u16 *) (icmp))[2];
191 case ICMP6_echo_request:
192 icmp->type = ICMP4_echo_request;
194 case ICMP6_echo_reply:
195 icmp->type = ICMP4_echo_reply;
197 case ICMP6_destination_unreachable:
202 case ICMP6_destination_unreachable_no_route_to_destination:
203 case ICMP6_destination_unreachable_beyond_scope_of_source_address:
204 case ICMP6_destination_unreachable_address_unreachable:
205 icmp->type = ICMP4_destination_unreachable;
207 ICMP4_destination_unreachable_destination_unreachable_host;
209 case ICMP6_destination_unreachable_destination_administratively_prohibited:
211 ICMP4_destination_unreachable;
213 ICMP4_destination_unreachable_communication_administratively_prohibited;
215 case ICMP6_destination_unreachable_port_unreachable:
216 icmp->type = ICMP4_destination_unreachable;
217 icmp->code = ICMP4_destination_unreachable_port_unreachable;
223 case ICMP6_packet_too_big:
226 icmp->type = ICMP4_destination_unreachable;
229 u32 advertised_mtu = clib_net_to_host_u32 (*((
u32 *) (icmp + 1)));
230 advertised_mtu -= 20;
232 ((
u16 *) (icmp))[3] = clib_host_to_net_u16 (advertised_mtu);
236 case ICMP6_time_exceeded:
239 icmp->type = ICMP4_time_exceeded;
242 case ICMP6_parameter_problem:
247 case ICMP6_parameter_problem_erroneous_header_field:
248 icmp->type = ICMP4_parameter_problem;
249 icmp->code = ICMP4_parameter_problem_pointer_indicates_error;
250 u32 pointer = clib_net_to_host_u32 (*((
u32 *) (icmp + 1)));
254 ((
u8 *) (icmp + 1))[0] =
257 case ICMP6_parameter_problem_unrecognized_next_header:
258 icmp->type = ICMP4_destination_unreachable;
259 icmp->code = ICMP4_destination_unreachable_port_unreachable;
261 case ICMP6_parameter_problem_unrecognized_option:
283 return (clib_net_to_host_u32 (ip_version_traffic_class_and_flow_label)
306 icmp46_header_t *icmp;
313 icmp = (icmp46_header_t *) (ip6 + 1);
317 if (ip6->
protocol != IP_PROTOCOL_ICMP6)
326 u16 *inner_L4_checksum, inner_l4_offset, inner_frag_offset,
328 u8 *inner_l4, inner_protocol;
339 if (
ip6_parse (vm, p, inner_ip6, ip6_pay_len - 8,
340 &inner_protocol, &inner_l4_offset, &inner_frag_offset))
343 inner_l4 =
u8_ptr_add (inner_ip6, inner_l4_offset);
346 if (inner_frag_offset)
348 ip6_frag_hdr_t *inner_frag =
349 (ip6_frag_hdr_t *)
u8_ptr_add (inner_ip6, inner_frag_offset);
350 inner_frag_id =
frag_id_6to4 (inner_frag->identification);
358 if (inner_protocol == IP_PROTOCOL_TCP)
362 else if (inner_protocol == IP_PROTOCOL_UDP)
366 else if (inner_protocol == IP_PROTOCOL_ICMP6)
368 icmp46_header_t *inner_icmp = (icmp46_header_t *) inner_l4;
370 inner_icmp->type = (inner_icmp->type == ICMP6_echo_request) ?
371 ICMP4_echo_request : ICMP4_echo_reply;
372 inner_protocol = IP_PROTOCOL_ICMP;
373 inner_L4_checksum = &inner_icmp->checksum;
385 if ((rv = inner_fn (inner_ip6, inner_ip4, inner_ctx)) != 0)
395 sizeof (*ip4) +
sizeof (*ip6) - inner_l4_offset);
400 inner_ip4->
protocol = inner_protocol;
403 if (inner_ip4->
protocol == IP_PROTOCOL_ICMP)
406 icmp46_header_t *inner_icmp = (icmp46_header_t *) inner_l4;
407 inner_icmp->checksum = 0;
410 clib_net_to_host_u16 (inner_ip4->
length)
411 - sizeof (*inner_ip4));
417 csum = *inner_L4_checksum;
430 icmp = (icmp46_header_t *)
u8_ptr_add (inner_l4, -
sizeof (*ip4) - 8);
440 if ((rv = fn (ip6, ip4, ctx)) != 0)
443 ip4->ip_version_and_header_length =
446 ip4->fragment_id = 0;
447 ip4->flags_and_fragment_offset = 0;
448 ip4->ttl = ip6->hop_limit;
449 ip4->protocol = IP_PROTOCOL_ICMP;
453 NULL) ? sizeof (*ip4) : (2 *
sizeof (*ip4) -
461 clib_net_to_host_u16 (ip4->length) -
int(* ip6_to_ip4_icmp_set_fn_t)(ip6_header_t *ip6, ip4_header_t *ip4, void *ctx)
IPv6 to IPv4 set call back function type.
#define clib_memcpy_fast(a, b, c)
u16 current_length
Nbytes between current data and the end of this buffer.
int(* ip6_to_ip4_tcp_udp_set_fn_t)(vlib_buffer_t *b, ip6_header_t *ip6, ip4_header_t *ip4, void *ctx)
static u16 ip6_get_port(vlib_main_t *vm, vlib_buffer_t *b, ip6_header_t *ip6, u16 buffer_len, u8 *ip_protocol, u16 *src_port, u16 *dst_port, u8 *icmp_type_or_tcp_flags, u32 *tcp_ack_number, u32 *tcp_seq_number)
Get L4 information like port number or ICMP id from IPv6 packet.
struct _tcp_header tcp_header_t
static int ip6_walk_ext_hdr(vlib_main_t *vm, vlib_buffer_t *b, const ip6_header_t *ip6_header, u8 find_hdr, u32 *length, ip6_ext_header_t **ext_hdr, ip6_ext_header_t **last_ext_hdr)
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 u8 ip6_translate_tos(u32 ip_version_traffic_class_and_flow_label)
Translate TOS value from IPv6 to IPv4.
vl_api_fib_path_type_t type
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
#define IP4_HEADER_FLAG_MORE_FRAGMENTS
#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.
static int icmp6_to_icmp(vlib_main_t *vm, vlib_buffer_t *p, ip6_to_ip4_icmp_set_fn_t fn, void *ctx, ip6_to_ip4_icmp_set_fn_t inner_fn, void *inner_ctx)
Translate ICMP6 packet to ICMP4.
VLIB buffer representation.
#define IP4_VERSION_AND_HEADER_LENGTH_NO_OPTIONS
#define u16_net_add(u, val)
static_always_inline int ip6_parse(vlib_main_t *vm, vlib_buffer_t *b, 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 ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
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)