More janitorial work
[vpp.git] / plugins / vcgn-plugin / vcgn / cnat_v4_tcp_in2out_stages.c
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,
47   foreach_cnat_ipv4_tcp_inside_input_error
48 #undef _
49   CNAT_IPV4_TCP_INSIDE_INPUT_N_ERROR,
50 } cnat_ipv4_tcp_inside_input_t;
51
52 static char * cnat_ipv4_tcp_inside_input_error_strings[] = {
53 #define _(sym,string) string,
54   foreach_cnat_ipv4_tcp_inside_input_error
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 +
179             STRUCT_OFFSET_OF(cnat_main_db_entry_t, user_ports);
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;
198     cnat_main_db_entry_t *db;
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;
240     cnat_main_db_entry_t *db;
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
254     if (PLATFORM_HANDLE_TTL_DECREMENT) {
255         if (PREDICT_FALSE(ip->ttl <= 1)) {
256             /* Try to generate ICMP error msg, as TTL is <= 1 */
257
258             if (icmpv4_generate_with_throttling
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
298         if(PREDICT_TRUE(!PLATFORM_DBL_SUPPORT)) {
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);
359                 if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) {
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             }
389             if (PREDICT_FALSE(global_debug_flag && CNAT_DEBUG_GLOBAL_ALL)) {
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 */
428         if (PREDICT_FALSE(ftp_alg_enabled && 
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
432             if(PREDICT_FALSE((db->flags & CNAT_DB_FLAG_PPTP_TUNNEL_ACTIVE) ||
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                           */
496                          CNAT_UPDATE_TCP_SEQ_ACK_CHECKSUM(seq, seq1)
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;
528                         FTP_ALG_DEBUG_PRINTF(
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
541                         FTP_ALG_DEBUG_PRINTF(
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                           */
599                          CNAT_UPDATE_TCP_SEQ_ACK_CHECKSUM(seq, seq1)
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:
615         if (PLATFORM_HANDLE_TTL_DECREMENT) {
616             /*
617              * Decrement TTL and update IPv4 checksum
618              */
619             ipv4_decr_ttl_n_calc_csum(ip);
620         }
621
622         tcp_in2out_nat_mss_n_checksum(ip, 
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
652         in2out_forwarding_count++;
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 {
663             V4_TCP_UPDATE_SESSION_FLAG(db, tcp);
664             CNAT_DB_TIMEOUT_RST(db);
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