FD.io VPP  v17.01.1-3-gc6833f8
Vector Packet Processing
cnat_v4_functions.h
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * cnat_v4_functions.h
4  *
5  * Copyright (c) 2007-2013 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19 
20 #ifndef __CNAT_V4_FUNCTOINS__
21 #define __CNAT_V4_FUNCTOINS__
22 
23 #include "tcp_header_definitions.h"
24 #include "cnat_db.h"
25 #include "spp_ctx.h"
26 
27 #include "platform_common.h"
28 
29 /*
30  * Defines and structures to enable TCP packet logging
31  */
32 #define TCP_LOGGING_DISABLE 0
33 #define TCP_LOGGING_ENABLE 1
34 #define TCP_LOGGING_PACKET_DUMP 2
35 #define TCP_LOGGING_SUMMARY_DUMP 3
36 
37 #define MAX_TCP_LOGGING_COUNT 1024
38 
39 typedef struct tcp_logging_struct {
51 
52 void tcp_debug_logging_dump (void);
53 void tcp_debug_logging_enable_disable (u32 enable_flag);
54 
55 void
57  u32 seq_num,
58  u32 ack_num,
59  u32 old_ip,
60  u32 new_ip,
61  u16 old_port,
62  u16 new_port,
67 
68 #define JLI printf("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__); fflush(stdout);
69 
70 #define CNAT_ICMP_DEST_UNREACHABLE 100
71 #define INCREMENT_NODE_COUNTER(c) \
72  em->counters[node_counter_base_index + c] += 1;
73 
74 #define V4_TCP_UPDATE_SESSION_FLAG(db, tcp) \
75 if ((tcp->flags & TCP_FLAG_ACK) && (tcp->flags & TCP_FLAG_SYN)) { \
76  db->flags |= CNAT_DB_FLAG_TCP_ACTIVE; \
77 } \
78 if ((tcp->flags & TCP_FLAG_RST) || (tcp->flags & TCP_FLAG_FIN)) { \
79  db->flags &= ~CNAT_DB_FLAG_TCP_ACTIVE; \
80  db->flags |= CNAT_DB_FLAG_TCP_CLOSING; \
81 }
82 
83 #define V4_TCP_UPDATE_SESSION_DB_FLAG(sdb, tcp) \
84 if ((tcp->flags & TCP_FLAG_ACK) && (tcp->flags & TCP_FLAG_SYN)) { \
85  sdb->flags |= CNAT_DB_FLAG_TCP_ACTIVE; \
86 } \
87 if ((tcp->flags & TCP_FLAG_RST) || (tcp->flags & TCP_FLAG_FIN)) { \
88  sdb->flags &= ~CNAT_DB_FLAG_TCP_ACTIVE; \
89  sdb->flags |= CNAT_DB_FLAG_TCP_CLOSING; \
90 }
91 
92 /*
93  * Code to recalculate checksum after ACK/SEQ number changes
94  * This macro assumes, we have pointer to tcp structure
95  * referenced by the name "tcp"
96  */
97 #define CNAT_UPDATE_TCP_SEQ_ACK_CHECKSUM(old_val32, new_val32) \
98 { \
99  u16 old_val_lower, old_val_upper, old_tcp_cr; \
100  u16 new_val_lower, new_val_upper, new_tcp_cr; \
101  u32 sum32; \
102  \
103  old_val_lower = ~((u16) old_val32); \
104  old_val_upper = ~((u16) (old_val32 >> 16)); \
105  old_tcp_cr = ~net2host16(&tcp->tcp_checksum); \
106  new_val_lower = (u16) new_val32; \
107  new_val_upper = (u16) (new_val32 >> 16); \
108  \
109  sum32 = old_val_lower + old_val_upper + old_tcp_cr + \
110  new_val_lower + new_val_upper; \
111  \
112  sum32 = (sum32 & 0xffff) + ((sum32 >> 16) & 0xffff); \
113  sum32 = (sum32 & 0xffff) + ((sum32 >> 16) & 0xffff); \
114  new_tcp_cr = ~((u16)sum32); \
115  \
116  tcp->tcp_checksum = host2net16(new_tcp_cr); \
117 }
118 
119 /*
120  * newchecksum = ~(~oldchecksum + ~old + new)
121  * old/new for l3 checksum: ip address
122  */
123 #define CNAT_UPDATE_L3_CHECKSUM_DECLARE \
124 u16 old_l3_1r, old_l3_2r; \
125 u16 old_l3_cr, new_l3_c; \
126 u32 new32;
127 
128 #define CNAT_UPDATE_L3_CHECKSUM(old_l3_1, old_l3_2, old_l3_c, \
129  new_l3_1, new_l3_2) \
130 old_l3_1r = ~(old_l3_1); \
131 old_l3_2r = ~(old_l3_2); \
132 old_l3_cr = ~(old_l3_c); \
133 new32 = old_l3_cr + old_l3_1r + old_l3_2r + new_l3_1 + new_l3_2; \
134 new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \
135 new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \
136 new_l3_c = ~((u16)new32);
137 
138 
139 /*
140  * newchecksum = ~(~oldchecksum + ~old + new)
141  * old/new for l3 checksum: ip address
142  * old/new for l4 checksum: ip address and port
143  */
144 #define CNAT_UPDATE_L3_L4_CHECKSUM_DECLARE \
145 u16 old_l3_1r, old_l3_2r, old_l4r; \
146 u16 old_l3_cr, old_l4_cr; \
147 u16 new_l3_c, new_l4_c; \
148 u32 sum32, new32;
149 
150 #define CNAT_UPDATE_L3_L4_CHECKSUM(old_l3_1, old_l3_2, old_l4, \
151  old_l3_c, old_l4_c, \
152  new_l3_1, new_l3_2, new_l4) \
153 old_l3_1r = ~(old_l3_1); \
154 old_l3_2r = ~(old_l3_2); \
155 old_l3_cr = ~(old_l3_c); \
156 sum32 = old_l3_1r + old_l3_2r + new_l3_1 + new_l3_2; \
157 new32 = old_l3_cr + sum32; \
158 new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \
159 new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \
160 new_l3_c = ~((u16)new32); \
161 old_l4r = ~(old_l4); \
162 old_l4_cr = ~(old_l4_c); \
163 sum32 += old_l4r + new_l4; \
164 new32 = old_l4_cr + sum32; \
165 new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \
166 new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \
167 new_l4_c = ~((u16)new32);
168 
169 /*
170  * For ICMP checksums, we don't use the top IP header for checksum calculation
171  */
172 #define CNAT_UPDATE_L3_ICMP_CHECKSUM(old_l3_1, old_l3_2, old_l4, \
173  old_l3_c, old_l4_c, \
174  new_l3_1, new_l3_2, new_l4) \
175 old_l3_1r = ~(old_l3_1); \
176 old_l3_2r = ~(old_l3_2); \
177 old_l3_cr = ~(old_l3_c); \
178 sum32 = old_l3_1r + old_l3_2r + new_l3_1 + new_l3_2; \
179 new32 = old_l3_cr + sum32; \
180 new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \
181 new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \
182 new_l3_c = ~((u16)new32); \
183 old_l4r = ~(old_l4); \
184 old_l4_cr = ~(old_l4_c); \
185 sum32 = old_l4r + new_l4; \
186 new32 = old_l4_cr + sum32; \
187 new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \
188 new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \
189 new_l4_c = ~((u16)new32);
190 
191 
192 /*
193  * icmp error type message:
194  * newchecksum = ~(~oldchecksum + ~old + new)
195  * old/new for outlayer ip checksum: ip address
196  * old/new for outlayer icmp checksum:
197  * out-layer: ip address
198  * inner-layer: ip addr, port, l3 checksum, l4 checksum
199  */
200 #define CNAT_UPDATE_ICMP_ERR_CHECKSUM_DECLARE \
201 u16 old_ip_1r, old_ip_2r, old_ip_port_r, old_ip_cr, old_icmp_cr; \
202 u16 new_icmp_c; \
203 u32 sum32;
204 
205 
206 #define CNAT_UPDATE_ICMP_ERR_CHECKSUM(old_ip_1, old_ip_2, old_ip_port, old_ip_c, old_icmp_c, \
207  new_ip_1, new_ip_2, new_ip_port, new_ip_c) \
208 old_ip_1r = ~(old_ip_1); \
209 old_ip_2r = ~(old_ip_2); \
210 old_ip_port_r = ~(old_ip_port); \
211 old_ip_cr = ~(old_ip_c); \
212 old_icmp_cr = ~(old_icmp_c); \
213 sum32 = old_ip_1r + old_ip_2r + new_ip_1 + new_ip_2 + \
214  old_ip_port_r + new_ip_port + old_ip_cr + new_ip_c; \
215 new32 = old_icmp_cr + sum32; \
216 new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \
217 new32 = (new32 & 0xffff) + ((new32 >> 16) & 0xffff); \
218 new_icmp_c = ~((u16)new32); \
219 
220 /*
221  * Add the two 16 bit parts of the 32 bit field
222  * Repeat it one more time to take care of any overflow
223  * Complement the u16 value and store it in network format
224  */
225 #define FILL_CHECKSUM(checksum_field, sum32) { \
226  sum32 = (sum32 & 0xffff) + ((sum32>>16) & 0xffff); \
227  sum32 = (sum32 & 0xffff) + ((sum32>>16) & 0xffff); \
228  checksum_field = clib_host_to_net_u16(~((u16) sum32)); \
229 }
230 
231 static inline void
233  tcp_hdr_type *tcp,
234  u32 *ip_addr_ptr,
235  u16 *tcp_port_addr_ptr,
236  u32 new_ip,
237  u16 new_port)
238 {
239  u32 old_ip_addr, old_ip32_r, new_ip32, sum32;
240  u16 old_port_r, old_ip_checksum_r, old_tcp_checksum_r;
241 
242  u16 *p16;
243 
244  p16 = (u16*) ip_addr_ptr;
245 
246  old_ip_addr = *ip_addr_ptr;
247  old_ip32_r = (((u16) ~clib_net_to_host_u16(*p16)) +
248  ((u16) ~clib_net_to_host_u16(*(p16+1))));
249 
250  old_port_r = ~clib_net_to_host_u16(*tcp_port_addr_ptr);
251 
252  *ip_addr_ptr = clib_host_to_net_u32(new_ip);
253 
254  new_ip32 = (new_ip & 0xffff) + ((new_ip >> 16) & 0xffff);
255 
256  old_ip_checksum_r = ~clib_net_to_host_u16(ip->checksum);
257 
258  /*
259  * Recalculate the new IP checksum
260  */
261  sum32 = old_ip32_r + new_ip32 + old_ip_checksum_r;
262 
263  FILL_CHECKSUM(ip->checksum, sum32);
264 
265  u16 frag_offset =
266  clib_net_to_host_u16((ip->frag_flags_offset));
267 
268  if(PREDICT_FALSE(frag_offset & IP_FRAG_OFFSET_MASK)) {
269  return; /* No need to update TCP fields */
270  }
271 
272  *tcp_port_addr_ptr = clib_host_to_net_u16(new_port);
273  old_tcp_checksum_r = ~clib_net_to_host_u16(tcp->tcp_checksum);
274 
275  /*
276  * Recalculate the new TCP checksum
277  */
278  sum32 = old_ip32_r + new_ip32 +
279  old_port_r + new_port + old_tcp_checksum_r;
280 
281  FILL_CHECKSUM(tcp->tcp_checksum, sum32);
282 
285  clib_net_to_host_u32(tcp->seq_num),
286  clib_net_to_host_u32(tcp->ack_num),
287  clib_net_to_host_u32(old_ip_addr),
288  clib_net_to_host_u32(*ip_addr_ptr),
289  ~old_port_r,
290  clib_net_to_host_u16(*tcp_port_addr_ptr),
291  ~old_ip_checksum_r,
292  clib_net_to_host_u16(ip->checksum),
293  ~old_tcp_checksum_r,
294  clib_net_to_host_u16(tcp->tcp_checksum));
295  }
296 }
297 
298 
300  tcp_hdr_type *tcp,
301  u32 ipv4_addr,
302  u16 port,
303  cnat_main_db_entry_t * db);
304 
305 void hex_dump(u8 * p, int len);
306 
308 
309 /*
310  * in cnat_v4_icmp_gen.c,
311  * return 1 if icmp msg allow to generate
312  * for this user
313  */
314 
316 
318 
322  u16 rx_uidb_index);
323 
325  u16 rx_uidb_index);
326 
327 void icmp_error_generate_v6(spp_ctx_t *ctx, u8 icmp_type,
328  u8 icmp_code, u16 uidb_index);
329 
330 void calculate_window_scale(tcp_hdr_type *tcp_header, u8 *scale);
331 
334  cnat_vrfmap_t *vrfmap);
335 void print_icmp_pkt (ipv4_header *ip);
336 void print_udp_pkt (ipv4_header *ip);
337 void print_tcp_pkt (ipv4_header *ip);
338 void print_ipv6_pkt (ipv6_header_t *ip);
339 
340 
341 #endif
342 
u32 icmp_msg_gen_allowed()
Definition: cnat_syslog.c:448
void icmp_error_generate_v6(spp_ctx_t *ctx, u8 icmp_type, u8 icmp_code, u16 uidb_index)
void print_icmp_pkt(ipv4_header *ip)
void ipv4_decr_ttl_n_calc_csum(ipv4_header *ipv4)
void print_tcp_pkt(ipv4_header *ip)
cnat_icmp_msg_t v6_icmp_msg_gen_allowed()
Definition: cnat_db.h:153
void hex_dump(u8 *p, int len)
void cnat_log_nat44_tcp_seq_mismatch(cnat_main_db_entry_t *db, cnat_vrfmap_t *vrfmap)
u32 get_my_svi_intf_ip_addr()
void tcp_debug_logging_dump(void)
u32 tcp_logging_enable_flag
static void cnat_v4_recalculate_tcp_checksum(ipv4_header *ip, tcp_hdr_type *tcp, u32 *ip_addr_ptr, u16 *tcp_port_addr_ptr, u32 new_ip, u16 new_port)
void tcp_in2out_nat_mss_n_checksum(ipv4_header *ip, tcp_hdr_type *tcp, u32 ipv4_addr, u16 port, cnat_main_db_entry_t *db)
#define PREDICT_FALSE(x)
Definition: clib.h:97
int icmpv6_generate_with_throttling(spp_ctx_t *ctx, ipv6_header_t *ipv4, u16 rx_uidb_index)
int icmpv4_generate_with_throttling(spp_ctx_t *ctx, ipv4_header *ipv4, u16 rx_uidb_index)
unsigned int u32
Definition: types.h:88
cnat_icmp_msg_t
Definition: cnat_db.h:522
void print_udp_pkt(ipv4_header *ip)
void print_ipv6_pkt(ipv6_header_t *ip)
unsigned short u16
Definition: types.h:57
#define IP_FRAG_OFFSET_MASK
unsigned char u8
Definition: types.h:56
struct _spp_ctx spp_ctx_t
void calculate_window_scale(tcp_hdr_type *tcp_header, u8 *scale)
Definition: cnat_util.c:2135
int v4_crc_zero_udp_allowed()
#define FILL_CHECKSUM(checksum_field, sum32)
void tcp_debug_logging_enable_disable(u32 enable_flag)
void tcp_debug_logging(u32 seq_num, u32 ack_num, u32 old_ip, u32 new_ip, u16 old_port, u16 new_port, u16 old_ip_crc, u16 new_ip_crc, u16 old_tcp_crc, u16 new_tcp_crc)
struct tcp_logging_struct tcp_logging_struct_t