17 #include "../ip/ip_frag.h" 19 #define IP4_MAP_T_DUAL_LOOP 1 58 }) ip4_mapt_pseudo_header_t;
60 #define frag_id_4to6(id) (id) 63 static u8 icmp_to_icmp6_updater_pointer_table[] =
111 switch (icmp->type) {
112 case ICMP4_echo_reply:
113 *receiver_port = ((
u16 *)icmp)[2];
114 icmp->type = ICMP6_echo_reply;
116 case ICMP4_echo_request:
117 *receiver_port = ((
u16 *)icmp)[2];
118 icmp->type = ICMP6_echo_request;
120 case ICMP4_destination_unreachable:
124 switch (icmp->code) {
125 case ICMP4_destination_unreachable_destination_unreachable_net:
126 case ICMP4_destination_unreachable_destination_unreachable_host:
127 icmp->type = ICMP6_destination_unreachable;
128 icmp->code = ICMP6_destination_unreachable_no_route_to_destination;
130 case ICMP4_destination_unreachable_protocol_unreachable:
131 icmp->type = ICMP6_parameter_problem;
132 icmp->code = ICMP6_parameter_problem_unrecognized_next_header;
134 case ICMP4_destination_unreachable_port_unreachable:
135 icmp->type = ICMP6_destination_unreachable;
136 icmp->code = ICMP6_destination_unreachable_port_unreachable;
138 case ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set:
139 icmp->type = ICMP6_packet_too_big;
142 u32 advertised_mtu = clib_net_to_host_u32(*((
u32 *)(icmp + 1)));
144 advertised_mtu += 20;
146 advertised_mtu = 1000;
149 *((
u32 *)(icmp + 1)) = clib_host_to_net_u32(advertised_mtu);
153 case ICMP4_destination_unreachable_source_route_failed:
154 case ICMP4_destination_unreachable_destination_network_unknown:
155 case ICMP4_destination_unreachable_destination_host_unknown:
156 case ICMP4_destination_unreachable_source_host_isolated:
157 case ICMP4_destination_unreachable_network_unreachable_for_type_of_service:
158 case ICMP4_destination_unreachable_host_unreachable_for_type_of_service:
159 icmp->type = ICMP6_destination_unreachable;
160 icmp->code = ICMP6_destination_unreachable_no_route_to_destination;
162 case ICMP4_destination_unreachable_network_administratively_prohibited:
163 case ICMP4_destination_unreachable_host_administratively_prohibited:
164 case ICMP4_destination_unreachable_communication_administratively_prohibited:
165 case ICMP4_destination_unreachable_precedence_cutoff_in_effect:
166 icmp->type = ICMP6_destination_unreachable;
167 icmp->code = ICMP6_destination_unreachable_destination_administratively_prohibited;
169 case ICMP4_destination_unreachable_host_precedence_violation:
175 case ICMP4_time_exceeded:
178 icmp->type = ICMP6_time_exceeded;
182 case ICMP4_parameter_problem:
186 switch (icmp->code) {
187 case ICMP4_parameter_problem_pointer_indicates_error:
188 case ICMP4_parameter_problem_bad_length:
189 icmp->type = ICMP6_parameter_problem;
190 icmp->code = ICMP6_parameter_problem_erroneous_header_field;
192 u8 ptr = icmp_to_icmp6_updater_pointer_table[*((
u8 *)(icmp + 1))];
196 *((
u32 *)(icmp + 1)) = clib_host_to_net_u32(ptr);
219 icmp46_header_t *icmp;
222 u16 *inner_L4_checksum = 0;
223 ip6_frag_hdr_t *inner_frag;
225 u32 inner_frag_offset;
229 ip_len = clib_net_to_host_u16(ip4->
length);
230 ASSERT(ip_len <= p->current_length);
232 icmp = (icmp46_header_t *)(ip4 + 1);
234 &recv_port, &inner_ip4)) {
235 *error = MAP_ERROR_ICMP;
244 *error = MAP_ERROR_ICMP;
260 *error = MAP_ERROR_FRAGMENTED;
268 icmp = (icmp46_header_t *) (ip4 + 1);
271 inner_frag = (ip6_frag_hdr_t *)
u8_ptr_add(inner_ip6,
sizeof(*inner_ip6));
281 icmp = (icmp46_header_t *)
u8_ptr_add(ip4,
sizeof(*ip4));
288 inner_L4_checksum = &((
tcp_header_t *) (inner_ip4 + 1))->checksum;
291 inner_L4_checksum = &((
udp_header_t *) (inner_ip4 + 1))->checksum;
292 if (!*inner_L4_checksum) {
295 *error = MAP_ERROR_ICMP;
299 }
else if (inner_ip4->
protocol == IP_PROTOCOL_ICMP) {
302 icmp46_header_t *inner_icmp = (icmp46_header_t *) (inner_ip4 + 1);
303 csum = inner_icmp->checksum;
306 inner_icmp->type = (inner_icmp->type == ICMP4_echo_request)?
307 ICMP6_echo_request:ICMP6_echo_reply;
312 inner_L4_checksum = &inner_icmp->checksum;
313 inner_ip4->
protocol = IP_PROTOCOL_ICMP6;
320 csum = *inner_L4_checksum;
335 inner_frag->next_hdr = inner_ip6->
protocol;
336 inner_frag->identification = inner_frag_id;
339 inner_ip6->
protocol = IP_PROTOCOL_IPV6_FRAGMENTATION;
341 clib_net_to_host_u16(inner_ip6->
payload_length) +
sizeof(*inner_frag));
390 u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
398 while (n_left_from > 0) {
401 while (n_left_from > 0 && n_left_to_next > 0) {
404 ip4_mapt_icmp_next_t next0;
410 pi0 = to_next[0] = from[0];
415 error0 = MAP_ERROR_NONE;
421 _ip4_map_t_icmp(d0, p0, &error0);
438 to_next, n_left_to_next, pi0,
451 u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
456 while (n_left_from > 0) {
459 while (n_left_from > 0 && n_left_to_next > 0) {
464 ip6_frag_hdr_t *frag0;
465 ip4_mapt_pseudo_header_t *pheader0;
466 ip4_mapt_fragmented_next_t next0;
469 pi0 = to_next[0] = from[0];
483 frag0 = (ip6_frag_hdr_t *)
u8_ptr_add(ip40,
sizeof(*ip40) -
sizeof(*frag0));
489 frag0->next_hdr = (ip40->
protocol == IP_PROTOCOL_ICMP) ? IP_PROTOCOL_ICMP6 : ip40->
protocol;
497 ip60->
payload_length = clib_host_to_net_u16(clib_net_to_host_u16(ip40->
length) -
sizeof(*ip40) +
sizeof(*frag0));
499 ip60->
protocol = IP_PROTOCOL_IPV6_FRAGMENTATION;
513 to_next, n_left_to_next, pi0,
526 u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
531 while (n_left_from > 0) {
534 #ifdef IP4_MAP_T_DUAL_LOOP 535 while (n_left_from >= 4 && n_left_to_next >= 2) {
541 u16 *checksum0, *checksum1;
542 ip6_frag_hdr_t *frag0, *frag1;
543 u32 frag_id0, frag_id1;
544 ip4_mapt_pseudo_header_t *pheader0, *pheader1;
545 ip4_mapt_tcp_udp_next_t next0, next1;
547 pi0 = to_next[0] = from[0];
548 pi1 = to_next[1] = from[1];
574 u16 udp_len = clib_host_to_net_u16(ip40->
length) -
sizeof(*ip40);
584 u16 udp_len = clib_host_to_net_u16(ip41->
length) -
sizeof(*ip40);
603 frag0 = (ip6_frag_hdr_t *)
u8_ptr_add(ip40,
sizeof(*ip40) -
sizeof(*frag0));
607 ip60 = (
ip6_header_t *) (((
u8 *)ip40) +
sizeof(*ip40) -
sizeof(*ip60));
615 frag1 = (ip6_frag_hdr_t *)
u8_ptr_add(ip41,
sizeof(*ip40) -
sizeof(*frag0));
619 ip61 = (
ip6_header_t *) (((
u8 *)ip41) +
sizeof(*ip40) -
sizeof(*ip60));
635 frag0->identification = frag_id0;
638 ip60->
protocol = IP_PROTOCOL_IPV6_FRAGMENTATION;
644 frag1->identification = frag_id1;
647 ip61->
protocol = IP_PROTOCOL_IPV6_FRAGMENTATION;
687 to_next, n_left_to_next, pi0, pi1,
692 while (n_left_from > 0 && n_left_to_next > 0) {
699 ip6_frag_hdr_t *frag0;
701 ip4_mapt_pseudo_header_t *pheader0;
702 ip4_mapt_tcp_udp_next_t next0;
704 pi0 = to_next[0] = from[0];
724 u16 udp_len = clib_host_to_net_u16(ip40->
length) -
sizeof(*ip40);
741 frag0 = (ip6_frag_hdr_t *)
u8_ptr_add(ip40,
sizeof(*ip40) -
sizeof(*frag0));
745 ip60 = (
ip6_header_t *) (((
u8 *)ip40) +
sizeof(*ip40) -
sizeof(*ip60));
757 frag0->identification = frag_id0;
760 ip60->
protocol = IP_PROTOCOL_IPV6_FRAGMENTATION;
785 to_next, n_left_to_next, pi0,
796 i32 *dst_port0,
u8 *error0, ip4_mapt_next_t *next0)
804 *error0 = (*dst_port0 == -1) ? MAP_ERROR_FRAGMENT_MEMORY : *error0;
809 *error0 = ip4_len0 < 40 ? MAP_ERROR_MALFORMED : *error0;
814 *error0 = ip4_len0 < 28 ? MAP_ERROR_MALFORMED : *error0;
816 }
else if (ip40->
protocol == IP_PROTOCOL_ICMP) {
820 else if (((icmp46_header_t *)
u8_ptr_add(ip40,
sizeof(*ip40)))->code == ICMP4_echo_reply ||
821 ((icmp46_header_t *)
u8_ptr_add(ip40,
sizeof(*ip40)))->code == ICMP4_echo_request)
824 *error0 = MAP_ERROR_BAD_PROTOCOL;
833 u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
841 while (n_left_from > 0) {
844 #ifdef IP4_MAP_T_DUAL_LOOP 845 while (n_left_from >= 4 && n_left_to_next >= 2) {
850 ip4_mapt_next_t next0 = 0, next1 = 0;
851 u16 ip4_len0, ip4_len1;
853 i32 dst_port0, dst_port1;
854 ip4_mapt_pseudo_header_t *pheader0, *pheader1;
856 pi0 = to_next[0] = from[0];
857 pi1 = to_next[1] = from[1];
862 error0 = MAP_ERROR_NONE;
863 error1 = MAP_ERROR_NONE;
869 ip4_len0 = clib_host_to_net_u16(ip40->
length);
870 ip4_len1 = clib_host_to_net_u16(ip41->
length);
874 error0 = MAP_ERROR_UNKNOWN;
880 error1 = MAP_ERROR_UNKNOWN;
915 error0 = MAP_ERROR_FRAGMENT_MEMORY;
921 error1 = MAP_ERROR_FRAGMENT_MEMORY;
927 clib_net_to_host_u16(ip40->
length));
933 clib_net_to_host_u16(ip41->
length));
941 n_left_to_next, pi0, pi1, next0, next1);
945 while (n_left_from > 0 && n_left_to_next > 0) {
950 ip4_mapt_next_t next0;
954 ip4_mapt_pseudo_header_t *pheader0;
956 pi0 = to_next[0] = from[0];
961 error0 = MAP_ERROR_NONE;
965 ip4_len0 = clib_host_to_net_u16(ip40->
length);
968 error0 = MAP_ERROR_UNKNOWN;
995 error0 = MAP_ERROR_UNKNOWN;
1001 clib_net_to_host_u16(ip40->
length));
1007 to_next, n_left_to_next, pi0,
1015 static char *map_t_error_strings[] = {
1016 #define _(sym,string) string, 1023 .name =
"ip4-map-t-fragmented",
1024 .vector_size =
sizeof(
u32),
1029 .error_strings = map_t_error_strings,
1041 .name =
"ip4-map-t-icmp",
1042 .vector_size =
sizeof(
u32),
1047 .error_strings = map_t_error_strings,
1059 .name =
"ip4-map-t-tcp-udp",
1060 .vector_size =
sizeof(
u32),
1065 .error_strings = map_t_error_strings,
1077 .name =
"ip4-map-t",
1078 .vector_size =
sizeof(
u32),
1083 .error_strings = map_t_error_strings,
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()
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
#define IP6_FRAG_NODE_NAME
always_inline int ip4_get_fragment_offset(ip4_header_t *i)
static_always_inline void ip4_map_t_classify(vlib_buffer_t *p0, map_domain_t *d0, ip4_header_t *ip40, u16 ip4_len0, i32 *dst_port0, u8 *error0, ip4_mapt_next_t *next0)
always_inline int ip4_is_fragment(ip4_header_t *i)
static_always_inline i32 ip4_map_fragment_get_port(ip4_header_t *ip4)
#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 uword ip4_map_t_icmp(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static uword ip4_map_t(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static_always_inline void ip4_map_t_embedded_address(map_domain_t *d, ip6_address_t *ip6, const ip4_address_t *ip4)
#define static_always_inline
ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
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)
ip4_mapt_fragmented_next_t
always_inline void * vlib_frame_vector_args(vlib_frame_t *f)
static_always_inline int ip4_icmp_to_icmp6_in_place(icmp46_header_t *icmp, u32 icmp_len, i32 *receiver_port, ip4_header_t **inner_ip4)
always_inline int ip4_is_first_fragment(ip4_header_t *i)
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.
static_always_inline u64 map_get_pfx_net(map_domain_t *d, u32 addr, u16 port)
uword os_get_cpu_number(void)
static_always_inline u64 map_get_sfx_net(map_domain_t *d, u32 addr, u16 port)
map_ip4_reass_t * map_ip4_reass_get(u32 src, u32 dst, u16 fragment_id, u8 protocol, u32 **pi_to_drop)
i32 ip4_get_port(ip4_header_t *ip, map_dir_e dir, u16 buffer_len)
#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.
#define IP4_HEADER_FLAG_MORE_FRAGMENTS
#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)
#define u8_ptr_add(ptr, index)
#define map_ip4_reass_unlock()
u8 * format_map_trace(u8 *s, va_list *args)
always_inline ip_csum_t ip_csum_with_carry(ip_csum_t sum, ip_csum_t x)
static_always_inline map_domain_t * ip4_map_get_domain(u32 adj_index, u32 *map_domain_index)
always_inline void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
static uword ip4_map_t_tcp_udp(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static uword ip4_map_t_fragmented(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static_always_inline int ip4_map_fragment_cache(ip4_header_t *ip4, u16 port)
#define VLIB_REGISTER_NODE(x,...)
always_inline vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
typedef CLIB_PACKED(struct{ip6_address_t daddr;ip6_address_t saddr;u8 unused[28];})
#define ip6_frag_hdr_offset_and_more(offset, more)
always_inline vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.