17 #include "../ip/ip_frag.h" 19 #define IP6_MAP_T_DUAL_LOOP 84 #ifdef IP6_MAP_T_OVERRIDE_TOS 85 return IP6_MAP_T_OVERRIDE_TOS;
110 switch (icmp->type) {
111 case ICMP6_echo_request:
112 *sender_port = ((
u16 *)icmp)[2];
113 icmp->type = ICMP4_echo_request;
115 case ICMP6_echo_reply:
116 *sender_port = ((
u16 *)icmp)[2];
117 icmp->type = ICMP4_echo_reply;
119 case ICMP6_destination_unreachable:
123 switch (icmp->code) {
124 case ICMP6_destination_unreachable_no_route_to_destination:
125 case ICMP6_destination_unreachable_beyond_scope_of_source_address:
126 case ICMP6_destination_unreachable_address_unreachable:
127 icmp->type = ICMP4_destination_unreachable;
128 icmp->code = ICMP4_destination_unreachable_destination_unreachable_host;
130 case ICMP6_destination_unreachable_destination_administratively_prohibited:
131 icmp->type = ICMP4_destination_unreachable;
132 icmp->code = ICMP4_destination_unreachable_communication_administratively_prohibited;
134 case ICMP6_destination_unreachable_port_unreachable:
135 icmp->type = ICMP4_destination_unreachable;
136 icmp->code = ICMP4_destination_unreachable_port_unreachable;
142 case ICMP6_packet_too_big:
146 icmp->type = ICMP4_destination_unreachable;
149 u32 advertised_mtu = clib_net_to_host_u32(*((
u32 *)(icmp + 1)));
150 advertised_mtu -= 20;
152 ((
u16 *)(icmp))[3] = clib_host_to_net_u16(advertised_mtu);
156 case ICMP6_time_exceeded:
160 icmp->type = ICMP4_time_exceeded;
163 case ICMP6_parameter_problem:
167 switch (icmp->code) {
168 case ICMP6_parameter_problem_erroneous_header_field:
169 icmp->type = ICMP4_parameter_problem;
170 icmp->code = ICMP4_parameter_problem_pointer_indicates_error;
171 u32 pointer = clib_net_to_host_u32(*((
u32*)(icmp + 1)));
177 case ICMP6_parameter_problem_unrecognized_next_header:
178 icmp->type = ICMP4_destination_unreachable;
179 icmp->code = ICMP4_destination_unreachable_port_unreachable;
181 case ICMP6_parameter_problem_unrecognized_option:
199 icmp46_header_t *icmp;
202 u32 ip4_sadr, inner_ip4_dadr;
206 icmp = (icmp46_header_t *)(ip6 + 1);
209 if (ip6->
protocol != IP_PROTOCOL_ICMP6) {
212 *error = MAP_ERROR_MALFORMED;
220 *error = MAP_ERROR_ICMP;
224 if (sender_port < 0) {
229 *error = MAP_ERROR_ICMP;
239 *error = MAP_ERROR_SEC_CHECK;
244 u16 *inner_L4_checksum, inner_l4_offset, inner_frag_offset, inner_frag_id;
245 u8 *inner_l4, inner_protocol;
258 if (
ip6_parse(inner_ip6, ip6_pay_len - 8,
259 &inner_protocol, &inner_l4_offset, &inner_frag_offset)) {
260 *error = MAP_ERROR_MALFORMED;
264 inner_l4 =
u8_ptr_add(inner_ip6, inner_l4_offset);
266 if (inner_frag_offset) {
267 ip6_frag_hdr_t *inner_frag = (ip6_frag_hdr_t *)
u8_ptr_add(inner_ip6, inner_frag_offset);
268 inner_frag_id =
frag_id_6to4(inner_frag->identification);
274 if (inner_protocol == IP_PROTOCOL_TCP) {
276 }
else if (inner_protocol == IP_PROTOCOL_UDP) {
278 }
else if (inner_protocol == IP_PROTOCOL_ICMP6) {
279 icmp46_header_t *inner_icmp = (icmp46_header_t *) inner_l4;
280 csum = inner_icmp->checksum;
283 inner_icmp->type = (inner_icmp->type == ICMP6_echo_request) ?
284 ICMP4_echo_request : ICMP4_echo_reply;
287 inner_protocol = IP_PROTOCOL_ICMP;
288 inner_L4_checksum = &inner_icmp->checksum;
290 *error = MAP_ERROR_BAD_PROTOCOL;
294 csum = *inner_L4_checksum;
303 *error = MAP_ERROR_SEC_CHECK;
311 *error = MAP_ERROR_SEC_CHECK;
324 inner_ip4->
protocol = inner_protocol;
327 if (inner_ip4->
protocol == IP_PROTOCOL_ICMP) {
341 icmp = (icmp46_header_t *)
u8_ptr_add(inner_l4, -
sizeof(*ip4) - 8);
358 (inner_ip6 ==
NULL)?
sizeof(*ip4):(2*
sizeof(*ip4) -
sizeof(*ip6)));
373 u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
381 while (n_left_from > 0) {
384 while (n_left_from > 0 && n_left_to_next > 0) {
392 pi0 = to_next[0] = from[0];
397 error0 = MAP_ERROR_NONE;
403 _ip6_map_t_icmp(d0, p0, &error0);
423 to_next, n_left_to_next, pi0,
436 u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
441 while (n_left_from > 0) {
444 #ifdef IP6_MAP_T_DUAL_LOOP 445 while(n_left_from >= 4 && n_left_to_next >= 2) {
449 ip6_frag_hdr_t *frag0, *frag1;
451 u16 frag_id0, frag_offset0,
452 frag_id1, frag_offset1;
453 u8 frag_more0, frag_more1;
456 pi0 = to_next[0] = from[0];
457 pi1 = to_next[1] = from[1];
492 sizeof(*ip40) -
vnet_buffer(p0)->map_t.v6.l4_offset +
sizeof(*ip60));
494 sizeof(*ip40) -
vnet_buffer(p1)->map_t.v6.l4_offset +
sizeof(*ip60));
500 clib_host_to_net_u16(frag_offset1 | (frag_more1?IP4_HEADER_FLAG_MORE_FRAGMENTS:0));
504 IP_PROTOCOL_ICMP:
vnet_buffer(p0)->map_t.v6.l4_protocol;
506 IP_PROTOCOL_ICMP:
vnet_buffer(p1)->map_t.v6.l4_protocol;
525 to_next, n_left_to_next, pi0, pi1,
530 while (n_left_from > 0 && n_left_to_next > 0) {
534 ip6_frag_hdr_t *frag0;
541 pi0 = to_next[0] = from[0];
563 sizeof(*ip40) -
vnet_buffer(p0)->map_t.v6.l4_offset +
sizeof(*ip60));
569 IP_PROTOCOL_ICMP:
vnet_buffer(p0)->map_t.v6.l4_protocol;
581 to_next, n_left_to_next, pi0,
594 u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
598 while (n_left_from > 0) {
601 #ifdef IP6_MAP_T_DUAL_LOOP 602 while(n_left_from >= 4 && n_left_to_next >= 2) {
608 u16 fragment_id0, flags0, *checksum0,
609 fragment_id1, flags1, *checksum1;
612 pi0 = to_next[0] = from[0];
613 pi1 = to_next[1] = from[1];
674 sizeof(*ip40) +
sizeof(*ip60) -
vnet_buffer(p0)->map_t.v6.l4_offset);
676 sizeof(*ip40) +
sizeof(*ip60) -
vnet_buffer(p1)->map_t.v6.l4_offset);
703 n_left_to_next, pi0, pi1, next0, next1);
707 while (n_left_from > 0 && n_left_to_next > 0) {
718 pi0 = to_next[0] = from[0];
755 sizeof(*ip40) +
sizeof(*ip60) -
vnet_buffer(p0)->map_t.v6.l4_offset);
771 to_next, n_left_to_next, pi0,
783 u32 l4_len0, ip6_frag_hdr_t *frag0)
792 *error0 = (*src_port0 != -1) ? *error0 : MAP_ERROR_FRAGMENT_DROPPED;
795 *error0 = l4_len0 <
sizeof(
tcp_header_t) ? MAP_ERROR_MALFORMED : *error0;
800 *error0 = l4_len0 <
sizeof(
udp_header_t) ? MAP_ERROR_MALFORMED : *error0;
804 }
else if (
vnet_buffer(p0)->map_t.v6.l4_protocol == IP_PROTOCOL_ICMP6) {
805 *error0 = l4_len0 <
sizeof(icmp46_header_t) ? MAP_ERROR_MALFORMED : *error0;
809 }
else if (((icmp46_header_t *)
u8_ptr_add(ip60,
vnet_buffer(p0)->map_t.v6.l4_offset))->code == ICMP6_echo_reply ||
810 ((icmp46_header_t *)
u8_ptr_add(ip60,
vnet_buffer(p0)->map_t.v6.l4_offset))->code == ICMP6_echo_request) {
815 *error0 = MAP_ERROR_BAD_PROTOCOL;
824 u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
832 while (n_left_from > 0) {
835 #ifdef IP6_MAP_T_DUAL_LOOP 836 while (n_left_from >= 4 && n_left_to_next >=2) {
842 u32 l4_len0, l4_len1;
843 i32 src_port0, src_port1;
845 ip6_frag_hdr_t *frag0, *frag1;
849 pi0 = to_next[0] = from[0];
850 pi1 = to_next[1] = from[1];
856 error0 = MAP_ERROR_NONE;
857 error1 = MAP_ERROR_NONE;
868 &
vnet_buffer(p0)->map_t.map_domain_index, &error0);
871 &
vnet_buffer(p1)->map_t.map_domain_index, &error1);
884 error0 = MAP_ERROR_MALFORMED;
892 error1 = MAP_ERROR_MALFORMED;
896 src_port0 = src_port1 = -1;
898 sizeof(*ip60) -
vnet_buffer(p0)->map_t.v6.l4_offset;
900 sizeof(*ip60) -
vnet_buffer(p1)->map_t.v6.l4_offset;
910 error0 = MAP_ERROR_SEC_CHECK;
916 error1 = MAP_ERROR_SEC_CHECK;
922 (src_port0 != -1) && (d0->
ea_bits_len != 0 || !d0->
rules) && (error0 == MAP_ERROR_NONE)) {
931 (src_port1 != -1) && (d1->
ea_bits_len != 0 || !d1->
rules) && (error1 == MAP_ERROR_NONE)) {
957 while (n_left_from > 0 && n_left_to_next > 0) {
965 ip6_frag_hdr_t *frag0;
969 pi0 = to_next[0] = from[0];
974 error0 = MAP_ERROR_NONE;
982 &
vnet_buffer(p0)->map_t.map_domain_index, &error0);
993 error0 = MAP_ERROR_MALFORMED;
999 sizeof(*ip60) -
vnet_buffer(p0)->map_t.v6.l4_offset;
1006 error0 = (src_port0 != -1) ? error0 : MAP_ERROR_FRAGMENT_MEMORY;
1009 error0 = l4_len0 <
sizeof(
tcp_header_t) ? MAP_ERROR_MALFORMED : error0;
1014 error0 = l4_len0 <
sizeof(
udp_header_t) ? MAP_ERROR_MALFORMED : error0;
1018 }
else if (
vnet_buffer(p0)->map_t.v6.l4_protocol == IP_PROTOCOL_ICMP6) {
1019 error0 = l4_len0 <
sizeof(icmp46_header_t) ? MAP_ERROR_MALFORMED : error0;
1021 if (((icmp46_header_t *)
u8_ptr_add(ip60,
vnet_buffer(p0)->map_t.v6.l4_offset))->code == ICMP6_echo_reply ||
1022 ((icmp46_header_t *)
u8_ptr_add(ip60,
vnet_buffer(p0)->map_t.v6.l4_offset))->code == ICMP6_echo_request)
1026 error0 = MAP_ERROR_BAD_PROTOCOL;
1034 error0 = MAP_ERROR_SEC_CHECK;
1041 (src_port0 != -1) && (d0->
ea_bits_len != 0 || !d0->
rules) && (error0 == MAP_ERROR_NONE)) {
1056 to_next, n_left_to_next, pi0,
1065 #define _(sym,string) string, 1072 .name =
"ip6-map-t-fragmented",
1073 .vector_size =
sizeof (
u32),
1090 .name =
"ip6-map-t-icmp",
1091 .vector_size =
sizeof (
u32),
1108 .name =
"ip6-map-t-tcp-udp",
1109 .vector_size =
sizeof (
u32),
1126 .name =
"ip6-map-t",
1127 .vector_size =
sizeof(
u32),
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
#define map_ip4_reass_lock()
static_always_inline u8 ip6_translate_tos(const ip6_header_t *ip6)
static uword ip6_map_t_tcp_udp(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
static_always_inline int ip6_parse(const ip6_header_t *ip6, u32 buff_len, u8 *l4_protocol, u16 *l4_offset, u16 *frag_hdr_offset)
static_always_inline int ip6_icmp_to_icmp6_in_place(icmp46_header_t *icmp, u32 icmp_len, i32 *sender_port, ip6_header_t **inner_ip6)
i32 ip6_get_port(ip6_header_t *ip6, map_dir_e dir, u16 buffer_len)
static uword ip6_map_t(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define u16_net_add(u, val)
always_inline void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
static_always_inline u32 ip6_map_t_embedded_address(map_domain_t *d, ip6_address_t *addr)
#define static_always_inline
ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
static u8 icmp6_to_icmp_updater_pointer_table[]
vlib_combined_counter_main_t * domain_counters
always_inline void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 cpu_index, u32 index, u32 packet_increment, u32 byte_increment)
static_always_inline i32 ip6_map_fragment_get(ip6_header_t *ip6, ip6_frag_hdr_t *frag, map_domain_t *d)
always_inline void * vlib_frame_vector_args(vlib_frame_t *f)
#define ip6_frag_hdr_more(hdr)
always_inline u16 ip_csum_fold(ip_csum_t c)
#define pool_elt_at_index(p, i)
u16 current_length
Nbytes between current data and the end of this buffer.
#define IP4_FRAG_NODE_NAME
static_always_inline u64 map_get_pfx_net(map_domain_t *d, u32 addr, u16 port)
uword os_get_cpu_number(void)
vlib_node_registration_t ip6_map_t_tcp_udp_node
(constructor) VLIB_REGISTER_NODE (ip6_map_t_tcp_udp_node)
static_always_inline int ip6_map_fragment_cache(ip6_header_t *ip6, ip6_frag_hdr_t *frag, map_domain_t *d, u16 port)
static_always_inline u64 map_get_sfx_net(map_domain_t *d, u32 addr, u16 port)
static_always_inline map_domain_t * ip6_map_get_domain(u32 adj_index, ip4_address_t *addr, u32 *map_domain_index, u8 *error)
map_ip4_reass_t * map_ip4_reass_get(u32 src, u32 dst, u16 fragment_id, u8 protocol, u32 **pi_to_drop)
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
always_inline ip_csum_t ip_csum_sub_even(ip_csum_t c, ip_csum_t x)
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
vlib_error_t error
Error code for buffers to be enqueued to error handler.
vlib_node_registration_t ip6_map_t_fragmented_node
(constructor) VLIB_REGISTER_NODE (ip6_map_t_fragmented_node)
always_inline u16 ip4_header_checksum(ip4_header_t *i)
#define IP4_HEADER_FLAG_MORE_FRAGMENTS
static uword ip6_map_t_icmp(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define clib_memcpy(a, b, c)
#define foreach_map_error
always_inline ip_csum_t ip_csum_add_even(ip_csum_t c, ip_csum_t x)
vlib_node_registration_t ip6_map_t_icmp_node
(constructor) VLIB_REGISTER_NODE (ip6_map_t_icmp_node)
#define ip6_frag_hdr_offset(hdr)
#define u8_ptr_add(ptr, index)
#define map_ip4_reass_unlock()
u8 * format_map_trace(u8 *s, va_list *args)
static uword ip6_map_t_fragmented(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static_always_inline u32 map_get_ip4(ip6_address_t *addr)
always_inline void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
static char * map_t_error_strings[]
vlib_node_registration_t ip6_map_t_node
(constructor) VLIB_REGISTER_NODE (ip6_map_t_node)
#define VLIB_REGISTER_NODE(x,...)
always_inline vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
#define IP4_VERSION_AND_HEADER_LENGTH_NO_OPTIONS
static_always_inline void ip6_map_t_classify(vlib_buffer_t *p0, ip6_header_t *ip60, map_domain_t *d0, i32 *src_port0, u8 *error0, ip6_mapt_next_t *next0, u32 l4_len0, ip6_frag_hdr_t *frag0)
ip6_mapt_fragmented_next_t
always_inline vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.