FD.io VPP  v16.06
Vector Packet Processing
cnat_v4_tcp_in2out_stages.c
Go to the documentation of this file.
1 /*
2  *---------------------------------------------------------------------------
3  * cnat_v4_tcp_in2out_stages.c - cnat_v4_tcp_in2out node pipeline stage functions
4  *
5  *
6  * Copyright (c) 2008-2014 Cisco and/or its affiliates.
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at:
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *---------------------------------------------------------------------------
19  */
20 
21 #include <vlib/vlib.h>
22 #include <vnet/vnet.h>
23 #include <vppinfra/error.h>
24 #include <vnet/buffer.h>
25 
26 #include "cnat_db.h"
27 /* #include <cnat_feature_data.h> */
28 #include "ipv4_packet.h"
29 #include "tcp_header_definitions.h"
30 #include "cnat_config.h"
31 #include "cnat_global.h"
32 #include "cnat_v4_functions.h"
33 #include "cnat_v4_ftp_alg.h"
34 #include "cnat_v4_pptp_alg.h"
35 
36 #define foreach_cnat_ipv4_tcp_inside_input_error \
37 _(TCP_NAT_IN, "packets received") \
38 _(TCP_NAT, "packets NATed") \
39 _(TCP_EXCEPTION, "packets to exception") \
40 _(TCP_TTL_GEN, "Generated TTL Expiry ICMP packet") \
41 _(TCP_TTL_DROP, "Could not generate TTL Expiry ICMP packet") \
42 _(TCP_SESSION_DROP, "Could not generate session") \
43 _(TCP_FRAG_DROP, "Non-first Fragment received")
44 
45 typedef enum {
46 #define _(sym,str) sym,
48 #undef _
51 
53 #define _(sym,string) string,
55 #undef _
56 
57 
58 
59 typedef struct cnat_v4_tcp_in2out_pipeline_data_ {
60  spp_node_main_vector_t *nmv;
61  /* Add additional pipeline stage data here... */
62  u32 bucket;
63  u16 src_port; /* Added for handling fragments */
64  u16 dst_port; /* Added for handling fragments */
65 } cnat_v4_tcp_in2out_pipeline_data_t;
66 
67 static cnat_v4_tcp_in2out_pipeline_data_t pctx_data[SPP_MAXDISPATCH];
68 
69 #define EXTRA_PIPELINE_ARGS_PROTO , cnat_v4_tcp_in2out_pipeline_data_t *pctx
70 #define EXTRA_PIPELINE_ARGS , pctx
71 
72 ALWAYS_INLINE(
73 static inline void
74 stage0(spp_ctx_t **ctxs, int index, spp_node_t *np,
75  u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO))
76 {
77  spp_ctx_t *ctx = ctxs[index];
78  /*
79  * Prefetch the context header. This is almost always
80  * the right thing to do
81  */
82  SPP_PREFETCH_CTX(ctx);
83 }
84 
85 ALWAYS_INLINE(
86 static inline void
87 stage1(spp_ctx_t **ctxs, int index, spp_node_t *np,
88  u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO))
89 {
90  spp_ctx_t *ctx = ctxs[index];
91  /* got ctx, prefetch packet data separately */
92  SPP_PREFETCH_CTX_DATA(ctx, 1*CACHE_DATA_QUANTUM);
93 }
94 
95 ALWAYS_INLINE(
96 static inline void
97 stage2(spp_ctx_t **ctxs, int index, spp_node_t *np,
98  u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO))
99 {
100  spp_ctx_t *ctx = ctxs[index];
101  u64 a, b, c;
102  u32 bucket;
103  cnat_feature_data_t *fd = (cnat_feature_data_t *)ctx->feature_data;
104  ipv4_header *ip;
105  tcp_hdr_type * tcp;
106  u8 *prefetch_target;
107 
108  INCREMENT_NODE_COUNTER(np, TCP_NAT_IN);
109 
110  /* extract the key from ctx and save it to feature_data */
111 
112  ip = (ipv4_header *)(ctx->current_header);
113  ctx->application_start = (ip->version_hdr_len_words & 0xf) << 2;
114  tcp = (tcp_hdr_type*) ((u8 *)ip + ctx->application_start);
115 
116  PLATFORM_CNAT_SET_RX_VRF(ctx,fd->dbl.k.k.vrf, CNAT_TCP, 1);
117  fd->dbl.k.k.ipv4 = spp_net_to_host_byte_order_32(&ip->src_addr);
118 
119  if(PREDICT_FALSE(ctx->ru.rx.frag)) {
120  /* Must have routed through cnat_v4_frag_in2out node
121  * Since feature data of the ctx is being used for other
122  * purposes here, copy them to extra stage argument
123  */
124  u16 *feature_data_ports = (u16 *)&ctx->feature_data[2];
125  pctx[index].src_port = fd->dbl.k.k.port = *feature_data_ports;
126  feature_data_ports++;
127  pctx[index].dst_port = *feature_data_ports;
128  } else {
129  fd->dbl.k.k.port = spp_net_to_host_byte_order_16(&tcp->src_port);
130  pctx[index].dst_port =
131  spp_net_to_host_byte_order_16(&tcp->dest_port);
132  }
133 
134 #if 0
135  /* extra info for evil mode, or default value for dst_ipv4 field in good mode */
136  fd->dbl.dst_ipv4 = address_dependent_filtering ?
137  spp_net_to_host_byte_order_32(&ip->dest_addr) : 0;
138 #endif
139 
140  CNAT_V4_GET_HASH(fd->dbl.k.key64,
141  bucket, CNAT_MAIN_HASH_MASK)
142 
143  prefetch_target = (u8 *)(&cnat_in2out_hash[bucket]);
144  pctx[index].bucket = bucket;
145 
146  /* Prefetch the hash bucket */
147  SPP_PREFETCH(prefetch_target, 0, LOAD);
148 
149 }
150 
151 ALWAYS_INLINE(
152 static inline void
153 stage3(spp_ctx_t **ctxs, int index, spp_node_t *np,
154  u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO))
155 {
156  u32 db_index;
157  u32 bucket;
158  uword prefetch_target0, prefetch_target1;
159 
160  bucket = pctx[index].bucket;
161 
162  /* read the hash bucket */
163  db_index = pctx[index].bucket = cnat_in2out_hash[bucket].next;
164  if (PREDICT_TRUE(db_index != EMPTY)) {
165 
166  /*
167  * Prefetch database keys. We save space by not cache-line
168  * aligning the DB entries. We don't want to waste LSU
169  * bandwidth prefetching stuff we won't need.
170  */
171 
172  prefetch_target0 = (uword)(cnat_main_db + db_index);
173 
174  SPP_PREFETCH(prefetch_target0, 0, LOAD);
175 
176  /* Just beyond DB key #2 */
177 
178  prefetch_target1 = prefetch_target0 +
180 
181  /* If the targets are in different lines, do the second prefetch */
182 
183  if (PREDICT_FALSE((prefetch_target0 & ~(SPP_CACHE_LINE_BYTES-1)) !=
184  (prefetch_target1 & ~(SPP_CACHE_LINE_BYTES-1)))) {
185 
186  SPP_PREFETCH(prefetch_target1, 0, LOAD);
187 
188  }
189  }
190 }
191 
192 static inline void
193 stage4(spp_ctx_t **ctxs, int index, spp_node_t *np,
194  u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO)
195 {
196  spp_ctx_t *ctx = ctxs[index];
197  u32 db_index = pctx[index].bucket;
199  cnat_feature_data_t *fd;
200 
201  /*
202  * Note: if the search already failed (empty bucket),
203  * the answer is already in the pipeline context structure
204  */
205  if (PREDICT_FALSE(db_index == EMPTY)) {
206  return;
207  }
208 
209  fd = (cnat_feature_data_t *)ctx->feature_data;
210 
211  /*
212  * Note: hash collisions suck. We can't easily prefetch around them.
213  * The first trip around the track will be fast. After that, maybe
214  * not so much...
215  */
216  do {
217 
218  db = cnat_main_db + db_index;
219  if (PREDICT_TRUE(db->in2out_key.key64 == fd->dbl.k.key64))
220  break;
221  db_index = db->in2out_hash.next;
222 
223  } while (db_index != EMPTY);
224 
225  /* even in evil mode, for in2out, we nat all packets regardless mode and dst_ip */
226 
227  /* Stick the answer back into the pipeline context structure */
228  pctx[index].bucket = db_index;
229 }
230 
231 ALWAYS_INLINE(
232 static inline void
233 stage5(spp_ctx_t **ctxs, int index, spp_node_t *np,
234  u8 *disp_used EXTRA_PIPELINE_ARGS_PROTO))
235 {
236  spp_ctx_t *ctx = ctxs[index];
237  u32 db_index = pctx[index].bucket;
238  cnat_feature_data_t *fd = (cnat_feature_data_t *)ctx->feature_data;
239  int disposition;
241  /* Below two pointers are just to keep the cnat_ftp_alg call happy*/
242  dslite_table_entry_t *dslite_entry_ptr = NULL;
243  ipv6_header_t *ipv6_hdr = NULL;
244  tcp_hdr_type *tcp;
245  ipv4_header *ip;
246  i8 delta;
247  u32 seq, seq1;
248  u32 window;
249  u8 scale;
250  int rc;
251 
252  ip = (ipv4_header *) ctx->current_header;
253 
255  if (PREDICT_FALSE(ip->ttl <= 1)) {
256  /* Try to generate ICMP error msg, as TTL is <= 1 */
257 
259  (ctx, ip, ctx->ru.rx.uidb_index)) {
260  /* Generated ICMP */
261  disposition = CNAT_REWRITE_OUTPUT;
262  INCREMENT_NODE_COUNTER(np, TCP_TTL_GEN);
263  } else {
264  /* Could not generated ICMP - drop the packet */
265  disposition = CNAT_DROP;
266  INCREMENT_NODE_COUNTER(np, TCP_TTL_DROP);
267  }
268  goto drop_pkt;
269  }
270  }
271 
272  if (PREDICT_FALSE(db_index == EMPTY)) {
273  if(PREDICT_FALSE(ctx->ru.rx.frag)) {
274  /* Must have routed through cnat_v4_frag_in2out node */
275  u16 frag_offset =
276  spp_net_to_host_byte_order_16(&(ip->frag_flags_offset));
277  if(PREDICT_FALSE(frag_offset & IP_FRAG_OFFSET_MASK)) {
278  INCREMENT_NODE_COUNTER(np, TCP_FRAG_DROP);
279  disposition = CNAT_DROP;
280  goto drop_pkt;
281  } else {
282  INCREMENT_NODE_COUNTER(np, TCP_EXCEPTION);
283  disposition = CNAT_V4_TCP_IE;
284  }
285  } else {
286  INCREMENT_NODE_COUNTER(np, TCP_EXCEPTION);
287  disposition = CNAT_V4_TCP_IE;
288  }
289  } else {
290  cnat_key_t dest_info;
291  cnat_session_entry_t *session_db = NULL;
292  db = cnat_main_db + db_index;
293  /* Handle destination sessions */
294  tcp = (tcp_hdr_type*) ((u8*)ip + ctx->application_start);
295  dest_info.k.port = pctx[index].dst_port;
296  dest_info.k.ipv4 = spp_net_to_host_byte_order_32(&(ip->dest_addr));
297 
299 
300  /* No DBL support, so just update the destn and proceed */
301  db->dst_ipv4 = dest_info.k.ipv4;
302  db->dst_port = dest_info.k.port;
303  goto update_pkt;
304  }
305 
306  if(PREDICT_FALSE(db->dst_ipv4 != dest_info.k.ipv4 ||
307  db->dst_port != dest_info.k.port)) {
308  if(PREDICT_TRUE(db->nsessions == 0)) {
309  /* Should be a static entry
310  * Note this session as the first session and log
311  */
312  cnat_add_dest_n_log(db, &dest_info);
313  } else if(PREDICT_FALSE(db->nsessions == 1)) {
314  /* Destn is not same as in main db. Multiple session
315  * scenario
316  */
317  dest_info.k.vrf = db->in2out_key.k.vrf;
318  session_db = cnat_handle_1to2_session(db, &dest_info);
319  if(PREDICT_FALSE(session_db == NULL)) {
320  disposition = CNAT_DROP;
321  INCREMENT_NODE_COUNTER(np, TCP_SESSION_DROP);
322  goto drop_pkt;
323  }
324  } else { /* There are already multiple destinations */
325  dest_info.k.vrf = db->in2out_key.k.vrf;
326  /* If session already exists,
327  * cnat_create_session_db_entry will return the existing db
328  * else create a new db
329  * If could not create, return NULL
330  */
331  session_db = cnat_create_session_db_entry(&dest_info,
332  db, TRUE);
333  if(PREDICT_FALSE(session_db == NULL)) {
334  disposition = CNAT_DROP;
335  INCREMENT_NODE_COUNTER(np, TCP_SESSION_DROP);
336  goto drop_pkt;
337  }
338  }
339  if(PREDICT_TRUE(session_db)) {
340  /* Have to repeat the window size check for new destinations */
341  window = (u32)spp_net_to_host_byte_order_16(
342  &tcp->window_size);
343  window = window << session_db->scale;
344  if(PREDICT_TRUE(!session_db->window)) {
345  calculate_window_scale(tcp, &scale);
346  session_db->scale = scale;
347  session_db->window = window;
348  } else if (PREDICT_FALSE(session_db->window <
349  window)) {
350  /* Update the db entry with window option from packet */
351  session_db->window = window;
352  } else {
353  /* Do nothing */
354  }
355  session_db->tcp_seq_num = spp_net_to_host_byte_order_32(
356  &tcp->seq_num);
357  session_db->ack_no = spp_net_to_host_byte_order_32(
358  &tcp->ack_num);
360  PLATFORM_DEBUG_PRINT("\n In2out SDB stages seq no = %u,"
361  " ack no = %u, window = %u\n",
362  session_db->tcp_seq_num,
363  session_db->ack_no,
364  session_db->window);
365  }
366  }
367  } else {
368  //Update the seq no and ack no for subsequent communication
369  //after connection establishment
370  //No need to update window here. Window is already updated
371  //during connection establishment
372  window = (u32)spp_net_to_host_byte_order_16(
373  &tcp->window_size);
374  window = window << db->scale;
375  if(PREDICT_FALSE(!ALG_ENABLED_DB(db))) {
376  //This check is done since proto_data is part of union in main
377  //db entry
378  db->proto_data.tcp_seq_chk.seq_no =
379  spp_net_to_host_byte_order_32(
380  &tcp->seq_num);
381  db->proto_data.tcp_seq_chk.ack_no =
382  spp_net_to_host_byte_order_32(
383  &tcp->ack_num);
384  }
385  if (PREDICT_FALSE(db->diff_window < window)) {
386  /* Update the db entry with window option from packet */
387  db->diff_window = window;
388  }
390  PLATFORM_DEBUG_PRINT("\n In2out MainDB seq no = %u,"
391  "\n ack no = %u\n",
392  db->proto_data.tcp_seq_chk.seq_no,
393  db->proto_data.tcp_seq_chk.ack_no);
394  PLATFORM_DEBUG_PRINT("\n In2out MAINDB window = %u\n",
395  db->diff_window);
396  }
397  }
398 update_pkt:
399 
400  INCREMENT_NODE_COUNTER(np, TCP_NAT);
401 
402  disposition = CNAT_REWRITE_OUTPUT;
403 
404  /* NAT the packet and update checksum (increamental) */
405 
406  /* If it is a non-first fragment, we need not worry about
407  * ALGs as the packet does not have TCP header..
408  * However, under a very race scenario when this non-first
409  * fragment is containing an FTP PORT command OR RTSP command
410  * we cannot handle that case.. in that case the ALG will fail
411  * Do not want to add a lot of complexity to handle one in million
412  * of such ALG case
413  */
414  u16 frag_offset =
415  spp_net_to_host_byte_order_16(&(ip->frag_flags_offset));
416 
417  if(PREDICT_FALSE(frag_offset & IP_FRAG_OFFSET_MASK)) {
418  /* Non first fragment.. no TCP header */
419  FTP_ALG_DEBUG_PRINTF("Non first frag.. cannot handle ALG");
420  goto handle_ttl_n_checksum;
421  }
422 
423  FTP_ALG_DEBUG_PRINTF("src port 0x%x, dst_port 0x%x",
424  spp_net_to_host_byte_order_16(&tcp->src_port),
425  spp_net_to_host_byte_order_16(&tcp->dest_port))
426 
427  /* handle FTP ALG */
429  (spp_net_to_host_byte_order_16(&tcp->src_port) == 21 ||
430  spp_net_to_host_byte_order_16(&tcp->dest_port) == 21))) {
431 
433  (db->flags & CNAT_DB_FLAG_PPTP_TUNNEL_INIT)))
434  {
435  /* FTP on a PPTP Control session? Ignore FTP */
436  goto handle_ttl_n_checksum;
437  }
438 
439  if (PREDICT_FALSE(tcp->flags & (TCP_FLAG_SYN | TCP_FLAG_RST |
440  TCP_FLAG_FIN))) {
441 
442  FTP_ALG_DEBUG_PRINTF("SYN Case setting delta = 0")
443 
444  /* reset the delta */
445  if(PREDICT_FALSE(session_db != NULL)) {
446  session_db->alg.delta = 0;
447  } else {
448  db->alg.delta = 0;
449  }
450 
451  } else {
452 
453  /* need to adjust seq # for in2out pkt if delta is not 0 */
454  if (PREDICT_TRUE((session_db && (session_db->alg.delta != 0))
455  || ((!session_db) && (db->alg.delta != 0)))) {
456  seq = net2host32(&tcp->seq_num);
457 
458  FTP_ALG_DEBUG_PRINTF("Orig Seq Num 0x%x", seq)
459  /*
460  * for ftp packets, due to PORT command translation,
461  * we may have cases that a packet/payload len gets
462  * changed for tcp, we need to adjust the packet's
463  * sequence numbers to match the changes. The delta
464  * of orig pkt len and new len is in alg_dlt[1] together
465  * with the sequence number that cuased the delta. When
466  * there are multiple len changes, we keep theprevious
467  * delta in alg_dlt[0] for case like pkt retransmission.
468  * So depends on packet seq number, we decide to use
469  * either latest delta or previous delta ([0])
470  * We won't be here if both delta values are 0
471  */
472  if(PREDICT_FALSE(session_db != NULL)) {
473  seq1 = seq > session_db->tcp_seq_num ?
474  (seq + session_db->alg.alg_dlt[1]):
475  (seq + session_db->alg.alg_dlt[0]);
476  } else {
477  seq1 = seq > db->proto_data.seq_pcp.tcp_seq_num ?
478  (seq + db->alg.alg_dlt[1]):
479  (seq + db->alg.alg_dlt[0]);
480  }
481 
482  FTP_ALG_DEBUG_PRINTF("Old_seq_num 0x%x New Seq Num 0x%x",
483  seq, seq1)
484 
485  if (PREDICT_TRUE(seq1 != seq)) {
486 
487  tcp->seq_num = host2net32(seq1);
488 
489  FTP_ALG_DEBUG_PRINTF("Old TCP Checksum 0x%x",
490  net2host16(&tcp->tcp_checksum))
491 
492  /*
493  * fix checksum incremental for seq # changes
494  * newchecksum = ~(~oldchecksum + ~old + new)
495  */
497  } /* There is a diff in seq */
498 
499  } /* ALG Delta is non zero */
500 
501  rc = cnat_ftp_alg((u8*) ip, &delta, db, dslite_entry_ptr, ipv6_hdr);
502 
503  FTP_ALG_DEBUG_PRINTF("cnat_ftp_alg rc 0x%x", rc)
504 
505  /*if located PORT cmd, packet being updated, take the delta and seq # */
506  if (PREDICT_FALSE(rc)) {
507 
508  /* set alg flag for this ftp control connection */
509  if(PREDICT_FALSE(session_db != NULL)) {
510  session_db->flags |= CNAT_DB_FLAG_ALG_CTRL_FLOW;
511  } else {
512  db->flags |= CNAT_DB_FLAG_ALG_CTRL_FLOW;
513  }
514 
515  /*
516  * rc != 0 indicates this packet has triggered a new pkt len delta
517  * we need to update db entry's seq# with seq# of this packet.
518  *
519  * Move alg_dlt[1] to [0], (current delta -> previous delta)
520  * then apply latest delta to alg_dlt[1] (keep [1] as latest delta)
521  */
522  if(PREDICT_FALSE(session_db != NULL)) {
523  session_db->tcp_seq_num = net2host32(&tcp->seq_num);
524  session_db->alg.alg_dlt[0] = session_db->alg.alg_dlt[1];
525 
526  /* accumulate the delta ! */
527  session_db->alg.alg_dlt[1] += delta;
529  "cnat_ftp_alg seq_num 0x%x, dlt0 0x%x, dlt1 0x%x",
530  session_db->tcp_seq_num,
531  session_db->alg.alg_dlt[0],
532  session_db->alg.alg_dlt[1])
533 
534  } else {
535  db->proto_data.seq_pcp.tcp_seq_num = net2host32(&tcp->seq_num);
536  db->alg.alg_dlt[0] = db->alg.alg_dlt[1];
537 
538  /* accumulate the delta ! */
539  db->alg.alg_dlt[1] += delta;
540 
542  "cnat_ftp_alg seq_num 0x%x, dlt0 0x%x, dlt1 0x%x",
543  db->proto_data.seq_pcp.tcp_seq_num,
544  db->alg.alg_dlt[0],
545  db->alg.alg_dlt[1])
546  }
547  ctx->current_length += delta;
548  }/* cnat_ftp_alg returned non zero */
549  } /* It is not a SYN, RST or FIN */
550  } else if (PREDICT_FALSE(rtsp_alg_port_num &&
551  ((spp_net_to_host_byte_order_16(&tcp->dest_port) == rtsp_alg_port_num) ||
552  (spp_net_to_host_byte_order_16(&tcp->src_port) == rtsp_alg_port_num))) ) {
553 
554  if (PREDICT_FALSE(tcp->flags & (TCP_FLAG_SYN | TCP_FLAG_RST |
555  TCP_FLAG_FIN))) {
556 
557  FTP_ALG_DEBUG_PRINTF("SYN Case setting delta = 0")
558 
559  /* reset the delta */
560  if(PREDICT_FALSE(session_db != NULL)) {
561  session_db->alg.delta = 0;
562  } else {
563  db->alg.delta = 0;
564  }
565 
566  } else {
567 #define RTSP_ALG_DELTA_MASK 0xFF
568  /* need to adjust seq # for in2out pkt if delta is not 0 */
569  if (PREDICT_FALSE((session_db &&
570  (session_db->alg.delta & RTSP_ALG_DELTA_MASK) != 0) ||
571  ((!session_db) &&
572  (db->alg.delta & RTSP_ALG_DELTA_MASK) != 0))) {
573  seq = net2host32(&tcp->seq_num);
574 
575  if(PREDICT_FALSE(session_db != NULL)) {
576  seq1 = seq > session_db->tcp_seq_num ?
577  (seq + db->alg.alg_dlt[1]):
578  (seq + db->alg.alg_dlt[0]);
579  } else {
580  seq1 = seq > db->proto_data.seq_pcp.tcp_seq_num ?
581  (seq + db->alg.alg_dlt[1]):
582  (seq + db->alg.alg_dlt[0]);
583  }
584 
585  FTP_ALG_DEBUG_PRINTF("Old_seq_num 0x%x New Seq Num 0x%x",
586  seq, seq1)
587 
588  if (PREDICT_TRUE(seq1 != seq)) {
589 
590  tcp->seq_num = host2net32(seq1);
591 
592  FTP_ALG_DEBUG_PRINTF("Old TCP Checksum 0x%x",
593  net2host16(&tcp->tcp_checksum))
594 
595  /*
596  * fix checksum incremental for seq # changes
597  * newchecksum = ~(~oldchecksum + ~old + new)
598  */
600  }
601 
602  }
603  }
604  if ((session_db && (!session_db->alg.il)) ||
605  ((!session_db) && (!db->alg.il))) {
606  cnat_rtsp_alg((u8*) ip,
607  &delta,
608  db,
609  ctx->current_length,
610  NULL,
611  NULL);
612  }
613  }
614 handle_ttl_n_checksum:
616  /*
617  * Decrement TTL and update IPv4 checksum
618  */
620  }
621 
623  tcp,
624  db->out2in_key.k.ipv4,
625  db->out2in_key.k.port,
626  db);
627 /* CNAT_PPTP_ALG_SUPPORT */
628  /* code to handle pptp control msgs */
629  if(PREDICT_FALSE(
630  (spp_net_to_host_byte_order_16(&tcp->dest_port) ==
631  TCP_PPTP_PORT))) {
632 
633  u32 ret;
634 
635  PPTP_DBG(3, "PPTP mgmt/ctrl msg recieved");
636 
637  ret = cnat_handle_pptp_msg(ctx, db , tcp, PPTP_PNS );
638 
639  if( PREDICT_FALSE( ret != CNAT_SUCCESS) ) {
640  PPTP_DBG(3, "PPTP mgmt/ctrl msg drop");
641  disposition = CNAT_DROP;
642  PPTP_INCR(ctrl_msg_drops);
643  goto drop_pkt;
644  }
645  }
646 
647 /* CNAT_PPTP_ALG_SUPPORT */
648 
649  /* update transaltion counters */
650  db->in2out_pkts++;
651 
653 
654  PLATFORM_CNAT_SET_TX_VRF(ctx,db->out2in_key.k.vrf);
655 
656  /* update the timer for good mode, or evil mode dst_ip match */
657 
658 // if (!address_dependent_filtering || fd->dbl.dst_ipv4 == db->dst_ipv4) {
659  if(PREDICT_FALSE(session_db != NULL)) {
660  V4_TCP_UPDATE_SESSION_DB_FLAG(session_db, tcp);
661  CNAT_DB_TIMEOUT_RST(session_db);
662  } else {
665  }
666 
667 // }
668 
669  }
670 
671  /* Pick up the answer and put it into the context */
672  fd->dbl.db_index = db_index;
673 
674 drop_pkt:
675 
676  DISP_PUSH_CTX(np, ctx, disposition, disp_used, last_disposition, last_contexts_ptr, last_nused_ptr);
677 
678 }
679 
#define ALG_ENABLED_DB(db)
Definition: cnat_db.h:694
cnat_main_db_entry_t * cnat_main_db
Definition: cnat_db_v2.c:195
cnat_session_entry_t * cnat_create_session_db_entry(cnat_key_t *ko, cnat_main_db_entry_t *bdb, u8 log)
Definition: cnat_db_v2.c:2597
#define SPP_CACHE_LINE_BYTES
a
Definition: bitmap.h:393
u16 delta
Definition: cnat_db.h:360
#define PREDICT_TRUE(x)
Definition: clib.h:98
#define NULL
Definition: clib.h:55
u32 tcp_seq_num
Definition: cnat_db.h:369
#define CNAT_DB_FLAG_PPTP_TUNNEL_INIT
Definition: cnat_db.h:170
#define foreach_cnat_ipv4_tcp_inside_input_error
u64 key64
Definition: cnat_db.h:109
#define net2host16(x)
#define V4_TCP_UPDATE_SESSION_FLAG(db, tcp)
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)
u32 ack_no
Definition: cnat_db.h:372
#define EXTRA_PIPELINE_ARGS_PROTO
Definition: cnat_db.h:153
#define CNAT_DB_FLAG_ALG_CTRL_FLOW
Definition: cnat_db.h:183
u8 address_dependent_filtering
Definition: cnat_config.c:72
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:62
index_slist_t in2out_hash
Definition: cnat_db.h:156
cnat_session_entry_t * cnat_handle_1to2_session(cnat_main_db_entry_t *mdb, cnat_key_t *dest_info)
Definition: cnat_db_v2.c:1012
int cnat_ftp_alg(u8 *pkt, i8 *delta, cnat_main_db_entry_t *db, dslite_table_entry_t *dslite_entry_ptr, ipv6_header_t *ipv6_hdr)
static char * cnat_ipv4_tcp_inside_input_error_strings[]
u8 ftp_alg_enabled
Definition: cnat_config.c:59
i8 alg_dlt[2]
Definition: cnat_db.h:361
static void stage2(vlib_main_t *vm, vlib_node_runtime_t *node, u32 buffer_index)
index_slist_t * cnat_in2out_hash
Definition: cnat_db_v2.c:190
#define CNAT_DB_TIMEOUT_RST(db)
Definition: cnat_db.h:561
#define PLATFORM_DEBUG_PRINT(...)
Definition: dslite_defs.h:106
u16 rtsp_alg_port_num
Definition: cnat_config.c:60
char i8
Definition: types.h:45
u8 scale
Definition: cnat_db.h:378
unsigned long u64
Definition: types.h:89
#define host2net32(x)
union cnat_session_entry_t::@166 alg
static void stage1(vlib_main_t *vm, vlib_node_runtime_t *node, u32 bi)
Definition: decap.c:64
#define PLATFORM_CNAT_SET_RX_VRF(ctx, rx_vrf, proto)
#define TCP_PPTP_PORT
#define FTP_ALG_DEBUG_PRINTF(...)
#define RTSP_ALG_DELTA_MASK
static void stage3(vlib_main_t *vm, vlib_node_runtime_t *node, u32 buffer_index)
static void stage4(vlib_main_t *vm, vlib_node_runtime_t *node, u32 buffer_index)
#define TCP_FLAG_SYN
#define PREDICT_FALSE(x)
Definition: clib.h:97
#define TCP_FLAG_RST
#define CNAT_UPDATE_TCP_SEQ_ACK_CHECKSUM(old_val32, new_val32)
int icmpv4_generate_with_throttling(spp_ctx_t *ctx, ipv4_header *ipv4, u16 rx_uidb_index)
u16 flags
Definition: cnat_db.h:348
void calculate_window_scale(tcp_hdr_type *tcp_header, u8 *scale)
Definition: cnat_util.c:2135
#define CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE
Definition: cnat_db.h:171
#define PPTP_INCR(ctr)
Definition: cnat_config.h:239
cnat_db_key_t k
Definition: cnat_db.h:108
#define CNAT_DEBUG_GLOBAL_ALL
Definition: cnat_cli.h:94
#define PPTP_DBG(debug,...)
void cnat_add_dest_n_log(cnat_main_db_entry_t *mdb, cnat_key_t *dest_info)
Definition: cnat_db_v2.c:1068
unsigned int u32
Definition: types.h:88
#define TRUE
Definition: cnat_db.h:78
#define PLATFORM_DBL_SUPPORT
#define INCREMENT_NODE_COUNTER(c)
#define CNAT_TCP
Definition: cnat_db.h:94
u32 global_debug_flag
cnat_ipv4_tcp_inside_input_t
u16 il
Definition: cnat_db.h:362
u64 uword
Definition: types.h:112
u32 window
Definition: cnat_db.h:375
Definition: cnat_db.h:336
unsigned short u16
Definition: types.h:57
#define IP_FRAG_OFFSET_MASK
#define CNAT_MAIN_HASH_MASK
Definition: cnat_db.h:56
unsigned char u8
Definition: types.h:56
#define net2host32(x)
always_inline void ipv4_decr_ttl_n_calc_csum(ipv4_header *ipv4)
Definition: cnat_global.c:61
struct _spp_ctx spp_ctx_t
u32 in2out_forwarding_count
#define EMPTY
Definition: index_list.h:24
#define PPTP_PNS
#define PLATFORM_HANDLE_TTL_DECREMENT
#define PLATFORM_CNAT_SET_TX_VRF(ctx, tx_vrf)
#define CNAT_V4_GET_HASH(key64, hash, mask)
Definition: cnat_db.h:536
#define V4_TCP_UPDATE_SESSION_DB_FLAG(sdb, tcp)
cnat_key_t in2out_key
Definition: cnat_db.h:201
#define TCP_FLAG_FIN