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];
177 u8 inner_l4_protocol;
179 u16 inner_frag_offset;
185 if (
ip6_parse (vm, b, inner_ip6, ip6_pay_len - 8,
186 &inner_l4_protocol, &inner_l4_offset,
190 if (inner_frag_offset &&
193 inner_frag_offset))))
196 inner_l4 =
u8_ptr_add (inner_ip6, inner_l4_offset);
197 if (inner_l4_protocol == IP_PROTOCOL_TCP ||
198 inner_l4_protocol == IP_PROTOCOL_UDP)
205 else if (inner_l4_protocol == IP_PROTOCOL_ICMP6)
207 icmp46_header_t *inner_icmp = (icmp46_header_t *) (inner_l4);
208 if (inner_icmp->type == ICMP6_echo_request)
211 *src_port = ((
u16 *) (inner_icmp))[2];
213 *dst_port = ((
u16 *) (inner_icmp))[2];
215 else if (inner_icmp->type == ICMP6_echo_reply)
218 *src_port = ((
u16 *) (inner_icmp))[2];
220 *dst_port = ((
u16 *) (inner_icmp))[2];
242 case ICMP6_echo_request:
243 icmp->type = ICMP4_echo_request;
245 case ICMP6_echo_reply:
246 icmp->type = ICMP4_echo_reply;
248 case ICMP6_destination_unreachable:
253 case ICMP6_destination_unreachable_no_route_to_destination:
254 case ICMP6_destination_unreachable_beyond_scope_of_source_address:
255 case ICMP6_destination_unreachable_address_unreachable:
256 icmp->type = ICMP4_destination_unreachable;
258 ICMP4_destination_unreachable_destination_unreachable_host;
260 case ICMP6_destination_unreachable_destination_administratively_prohibited:
262 ICMP4_destination_unreachable;
264 ICMP4_destination_unreachable_communication_administratively_prohibited;
266 case ICMP6_destination_unreachable_port_unreachable:
267 icmp->type = ICMP4_destination_unreachable;
268 icmp->code = ICMP4_destination_unreachable_port_unreachable;
274 case ICMP6_packet_too_big:
277 icmp->type = ICMP4_destination_unreachable;
280 u32 advertised_mtu = clib_net_to_host_u32 (*((
u32 *) (icmp + 1)));
281 advertised_mtu -= 20;
283 ((
u16 *) (icmp))[3] = clib_host_to_net_u16 (advertised_mtu);
287 case ICMP6_time_exceeded:
290 icmp->type = ICMP4_time_exceeded;
293 case ICMP6_parameter_problem:
298 case ICMP6_parameter_problem_erroneous_header_field:
299 icmp->type = ICMP4_parameter_problem;
300 icmp->code = ICMP4_parameter_problem_pointer_indicates_error;
301 u32 pointer = clib_net_to_host_u32 (*((
u32 *) (icmp + 1)));
305 ((
u8 *) (icmp + 1))[0] =
308 case ICMP6_parameter_problem_unrecognized_next_header:
309 icmp->type = ICMP4_destination_unreachable;
310 icmp->code = ICMP4_destination_unreachable_port_unreachable;
312 case ICMP6_parameter_problem_unrecognized_option:
334 return (clib_net_to_host_u32 (ip_version_traffic_class_and_flow_label)
357 icmp46_header_t *icmp;
360 ip6_address_t old_src, old_dst;
364 icmp = (icmp46_header_t *) (ip6 + 1);
368 if (ip6->
protocol != IP_PROTOCOL_ICMP6)
377 u16 *inner_L4_checksum, inner_l4_offset, inner_frag_offset,
379 u8 *inner_l4, inner_protocol;
390 if (
ip6_parse (vm, p, inner_ip6, ip6_pay_len - 8,
391 &inner_protocol, &inner_l4_offset, &inner_frag_offset))
394 inner_l4 =
u8_ptr_add (inner_ip6, inner_l4_offset);
397 if (inner_frag_offset)
399 ip6_frag_hdr_t *inner_frag =
400 (ip6_frag_hdr_t *)
u8_ptr_add (inner_ip6, inner_frag_offset);
401 inner_frag_id =
frag_id_6to4 (inner_frag->identification);
409 if (inner_protocol == IP_PROTOCOL_TCP)
413 else if (inner_protocol == IP_PROTOCOL_UDP)
417 else if (inner_protocol == IP_PROTOCOL_ICMP6)
419 icmp46_header_t *inner_icmp = (icmp46_header_t *) inner_l4;
421 inner_icmp->type = (inner_icmp->type == ICMP6_echo_request) ?
422 ICMP4_echo_request : ICMP4_echo_reply;
423 inner_protocol = IP_PROTOCOL_ICMP;
424 inner_L4_checksum = &inner_icmp->checksum;
431 old_src.as_u64[0] = inner_ip6->
src_address.as_u64[0];
432 old_src.as_u64[1] = inner_ip6->
src_address.as_u64[1];
433 old_dst.as_u64[0] = inner_ip6->
dst_address.as_u64[0];
434 old_dst.as_u64[1] = inner_ip6->
dst_address.as_u64[1];
436 if ((rv = inner_fn (inner_ip6, inner_ip4, inner_ctx)) != 0)
446 sizeof (*ip4) +
sizeof (*ip6) - inner_l4_offset);
451 inner_ip4->
protocol = inner_protocol;
454 if (inner_ip4->
protocol == IP_PROTOCOL_ICMP)
457 icmp46_header_t *inner_icmp = (icmp46_header_t *) inner_l4;
458 inner_icmp->checksum = 0;
461 clib_net_to_host_u16 (inner_ip4->
length)
462 - sizeof (*inner_ip4));
468 csum = *inner_L4_checksum;
481 icmp = (icmp46_header_t *)
u8_ptr_add (inner_l4, -
sizeof (*ip4) - 8);
491 if ((rv = fn (ip6, ip4, ctx)) != 0)
494 ip4->ip_version_and_header_length =
497 ip4->fragment_id = 0;
498 ip4->flags_and_fragment_offset = 0;
499 ip4->ttl = ip6->hop_limit;
500 ip4->protocol = IP_PROTOCOL_ICMP;
504 NULL) ? sizeof (*ip4) : (2 *
sizeof (*ip4) -
512 clib_net_to_host_u16 (ip4->length) -
vl_api_wireguard_peer_flags_t flags
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.
vl_api_ip_port_and_mask_t dst_port
#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.
vl_api_ip_port_and_mask_t src_port
#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)