Initial commit of vpp code.
[vpp.git] / vnet / vnet / vcgn / cnat_v4_functions.h
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 {
40     u32 seq_num;
41     u32 ack_num;
42     u32 old_ip;
43     u32 new_ip;
44     u16 old_port;
45     u16 new_port;
46     u16 old_ip_crc;
47     u16 new_ip_crc;
48     u16 old_tcp_crc;
49     u16 new_tcp_crc;
50 } tcp_logging_struct_t;
51
52 void tcp_debug_logging_dump (void);
53 void tcp_debug_logging_enable_disable (u32 enable_flag);
54
55 void
56 tcp_debug_logging (
57     u32 seq_num,
58     u32 ack_num,
59     u32 old_ip,
60     u32 new_ip,
61     u16 old_port,
62     u16 new_port,
63     u16 old_ip_crc,
64     u16 new_ip_crc,
65     u16 old_tcp_crc,
66     u16 new_tcp_crc);
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
232 cnat_v4_recalculate_tcp_checksum (ipv4_header *ip,
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
283     if (PREDICT_FALSE(tcp_logging_enable_flag)) {
284         tcp_debug_logging(
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
299 inline void tcp_in2out_nat_mss_n_checksum (ipv4_header *ip,
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
307 u32 get_my_svi_intf_ip_addr();
308
309 /* 
310  * in cnat_v4_icmp_gen.c,
311  * return 1 if icmp msg allow to generate
312  * for this user
313  */
314
315 u32 icmp_msg_gen_allowed ();
316
317 cnat_icmp_msg_t v6_icmp_msg_gen_allowed();
318
319 int v4_crc_zero_udp_allowed();
320 void ipv4_decr_ttl_n_calc_csum(ipv4_header *ipv4);
321 int icmpv4_generate_with_throttling (spp_ctx_t *ctx, ipv4_header *ipv4,
322                                      u16 rx_uidb_index);
323                                             
324 int icmpv6_generate_with_throttling (spp_ctx_t *ctx, ipv6_header_t *ipv4,
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
332 void cnat_log_nat44_tcp_seq_mismatch(
333                    cnat_main_db_entry_t *db,
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