2 // Copyright (c) 2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
23 #include <rte_common.h>
24 #include <rte_malloc.h>
27 #include <rte_byteorder.h>
28 #include <rte_table_lpm.h>
29 #include <rte_table_hash.h>
30 #include <rte_pipeline.h>
34 #include <rte_jhash.h>
35 #include <rte_cycles.h>
36 #include "pipeline_cgnapt_common.h"
37 #include "pipeline_actions_common.h"
38 #include "pipeline_cgnapt_be.h"
39 #include "hash_func.h"
40 #include "lib_ftp_alg.h"
41 #include "vnf_common.h"
42 #include "pipeline_common_be.h"
43 #include "rte_ct_tcp.h"
44 #include "rte_cnxn_tracking.h"
49 rte_ct_create_cnxn_hashkey(
59 struct rte_mbuf *lib_alg_pkt;
60 enum {PRIVATE, PUBLIC};
61 struct rte_hash_parameters ftp_alg_hash_params = {
65 .key_len = sizeof(struct ftp_alg_key),
66 .hash_func = rte_jhash,
67 .hash_func_init_val = 0,
70 struct rte_hash *ftp_alg_hash_handle;
73 * ftp_alg Init function
75 void lib_ftp_alg_init(void)
77 printf("NAT FTP ALG initialization ...\n");
79 /* FTP ALG hash table initialization */
81 ftp_alg_hash_handle = rte_hash_create(&ftp_alg_hash_params);
84 if (ftp_alg_hash_handle == NULL)
85 printf("FTP ALG rte_hash_create failed ...\n");
87 printf("ftp_alg_hash_table %p\n\n",
88 (void *)ftp_alg_hash_handle);
94 * ftp_alg table retreive function
99 struct ftp_alg_table_entry *retrieve_ftp_alg_entry(struct ftp_alg_key alg_key)
101 struct ftp_alg_table_entry *ret_alg_data = NULL;
105 int ret = rte_hash_lookup_data(ftp_alg_hash_handle, &alg_key,
106 (void **)&ret_alg_data);
109 printf("alg-hash lookup failed ret %d, EINVAL %d, ENOENT %d\n",
110 ret, EINVAL, ENOENT);
120 * ftp_alg table entry delete
121 * Input - ipaddress, portid
122 * Output - sucess or failure
124 static int remove_ftp_alg_entry(uint32_t ipaddr, uint8_t portid)
127 /* need to lock here if multi-threaded... */
128 /* rte_hash_del_key is not thread safe */
129 struct ftp_alg_key alg_key;
130 alg_key.l4port = rte_bswap16(portid);
131 alg_key.ip_address = rte_bswap32(ipaddr);
136 printf("remove_alg_entry ip %x, port %d\n", alg_key.ip_address,
139 return rte_hash_del_key(ftp_alg_hash_handle, &alg_key);
142 * ftp_alg table entry add
143 * Input - ipaddress, portid
144 * Output - sucess or failure
147 populate_ftp_alg_entry(uint32_t ipaddr, uint8_t portid)
149 /* need to lock here if multi-threaded */
150 /* rte_hash_add_key_data is not thread safe */
151 struct ftp_alg_key alg_key;
152 alg_key.l4port = rte_bswap16(portid);
153 //arp_key.ip = rte_bswap32(ipaddr);
154 alg_key.ip_address = rte_bswap32(ipaddr);
159 //lib_arp_populate_called++;
162 printf("populate_ftp_alg_entry ip %x, port %d\n", alg_key.ip_address,
166 struct ftp_alg_table_entry *new_alg_data =
167 retrieve_ftp_alg_entry(alg_key);
170 printf("alg_entry exists ip%x, port %d\n", alg_key.ip_address,
173 //lib_arp_duplicate_found++;
176 new_alg_data = (struct ftp_alg_table_entry *)
177 malloc(sizeof(struct ftp_alg_table_entry));
180 printf("new_alg_data could not be allocated\n");
184 //new_alg_data->status = INCOMPLETE;
185 new_alg_data->l4port = rte_bswap16(portid);
186 new_alg_data->ip_address = rte_bswap32(ipaddr);
187 rte_hash_add_key_data(ftp_alg_hash_handle, &alg_key, new_alg_data);
190 // print entire hash table
192 ("\tALG: table update - ip=%d.%d.%d.%d on port=%d\n",
193 (alg_key.ip_address >> 24),
194 ((alg_key.ip_address & 0x00ff0000) >> 16),
195 ((alg_key.ip_address & 0x0000ff00) >> 8),
196 ((alg_key.ip_address & 0x000000ff)), portid);
197 /* print_arp_table(); */
203 * ftp_alg payload modification for PORT and PASV command
204 * Input - cgnapt table entry - for taking the public /translated ip/port ,
205 * incoming PORT/PASV string, Session type - PORT or PASV
206 * Output - Translated string
208 int ftp_alg_modify_payload(
209 struct cgnapt_table_entry *egress_entry,
211 char *port_string_translated, int ftp_session_type)
213 uint32_t transport_ip;
214 uint16_t transport_port;
215 uint16_t tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
216 uint16_t new_port_string_length;
218 uint8_t *bptr_public_address;
220 transport_ip = egress_entry->data.pub_ip;
221 transport_port = egress_entry->data.pub_port;
222 tmp5 = (uint16_t) (transport_port/0x100);
223 tmp6 = (uint16_t) (transport_port % 0x100);
225 transport_ip = rte_bswap32(transport_ip);
227 bptr_public_address = (uint8_t *) &transport_ip;
229 tmp4 = bptr_public_address[3];
230 tmp3 = bptr_public_address[2];
231 tmp2 = bptr_public_address[1];
232 tmp1 = bptr_public_address[0];
234 if (ftp_session_type == 1)
235 sprintf(port_string_translated, FTP_PASV_PARAMETER_STRING,
236 FTP_PASV_RETURN_CODE, tmp1, tmp2, tmp3, tmp4,
239 sprintf(port_string_translated, FTP_PORT_PARAMETER_STRING,
240 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6);
242 printf("FTP ALG: FTP new string: Len:%d %s\n",
243 (uint16_t) strlen(port_string_translated)-2,
244 port_string_translated);
246 printf("FTP non translated PASV string: Len:%d, %s\n",
247 (uint16_t)strlen(port_string)-2, port_string);
248 printf("old strlen:%d new strlen:%d\n",
249 (int)strlen(port_string),
250 (int)strlen(port_string_translated));
253 return(new_port_string_length =
254 (uint16_t) strlen(port_string_translated));
258 * ftp_alg modify packet len (due to change in len of FTP payload )
260 * Output - Length append /Trimmed Pkt
262 static inline void ftp_alg_modify_pkt_len(struct rte_mbuf *pkt)
264 uint16_t pkt_length = 0;
265 int ip_hdr_size_bytes = rte_ct_get_IP_hdr_size(pkt);
266 void *iphdr = RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START);
268 if (ip_hdr_size_bytes == IPv4_HEADER_SIZE) {
269 struct ipv4_hdr *ihdr4 = (struct ipv4_hdr *)iphdr;
270 pkt_length = rte_bswap16(ihdr4->total_length) + ETH_HDR_SIZE;
271 } else if (ip_hdr_size_bytes == IPv6_HEADER_SIZE) {
272 struct ipv6_hdr *ihdr6 = (struct ipv6_hdr *)iphdr;
273 pkt_length = rte_bswap16(ihdr6->payload_len) +
274 IPv6_HEADER_SIZE + ETH_HDR_SIZE;
277 uint16_t mbuf_pkt_length = rte_pktmbuf_pkt_len(pkt);
279 if (pkt_length == mbuf_pkt_length)
282 if (pkt_length < mbuf_pkt_length) {
283 rte_pktmbuf_trim(pkt, mbuf_pkt_length - pkt_length);
287 /* pkt_length > mbuf_pkt_length */
288 rte_pktmbuf_append(pkt, pkt_length - mbuf_pkt_length);
292 * ftp_alg IP HDR size calculation
294 * Output - Length of IP HDR
297 /* same as rte_ct_get_IP_hdr_size()*/
298 uint16_t ftp_alg_get_IP_hdr_size(struct rte_mbuf *pkt)
300 /* NOTE: Only supporting IP headers with no options at this time
301 * so header is fixed size
304 uint8_t hdr_chk = RTE_MBUF_METADATA_UINT8(pkt, IP_START);
305 hdr_chk = hdr_chk >> 4;
307 if (hdr_chk == IP_VERSION_4)
308 return IPv4_HEADER_SIZE;
309 else if (hdr_chk == IP_VERSION_6)
310 return IPv6_HEADER_SIZE;
311 else /* Not IPv4 header with no options, return negative. */
317 * ftp_alg checksum re-computing due to change in payload , uses rte function,
318 * if HW Checksum is supported s/w checksum will be disabled
319 * Input - IP HDR and TCP HDR
320 * Output - Length of IP HDR
322 static void ftp_alg_compute_checksums(
324 struct tcp_hdr *t_hdr)
325 /* same as rte_synproxy_compute_checksums*/
328 * calculate IP and TCP checksums.
329 * Note that both checksum routines require
330 * checksum fields to be set to zero, and the the checksum is in the
331 * correct byte order, so no rte_bswap16 is required.
334 int8_t hdr_chk = rte_ct_ipversion(i_hdr);
337 if (hdr_chk == IP_VERSION_4) {
338 struct ipv4_hdr *i4_hdr = (struct ipv4_hdr *)i_hdr;
339 i4_hdr->hdr_checksum = 0;
341 t_hdr->cksum = rte_ipv4_udptcp_cksum(i4_hdr, t_hdr);
344 printf("cksum %x\n", rte_bswap32(t_hdr->cksum));
347 i4_hdr->hdr_checksum = rte_ipv4_cksum(i4_hdr);
348 } else if (hdr_chk == IP_VERSION_6) {
349 struct ipv6_hdr *i6_hdr = (struct ipv6_hdr *)i_hdr;
351 t_hdr->cksum = rte_ipv6_udptcp_cksum(i6_hdr, t_hdr);
356 * ftp_alg adjusting ACK from other end ;
357 * ACK field of return packet to be adjusted
358 * to the same value of length modified in the payload
359 * Input - pkt, ack diff - delta
360 * Output - None(void)
362 static void ftp_alg_adjust_tcp_ack(struct rte_mbuf *pkt, int16_t ackSeqdiff)
364 /*Since v6 is not supported now*/
365 uint16_t ip_hdr_size_bytes = IPv4_HEADER_SIZE;
366 struct ipv4_hdr *iphdr = (struct ipv4_hdr *)
367 RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START);
368 struct tcp_hdr *thdr = (struct tcp_hdr *)
369 RTE_MBUF_METADATA_UINT32_PTR(pkt,
370 IP_START + ip_hdr_size_bytes);
372 * recv_ack and total length first to be chnaged to host byte order
373 * and then do the addition and then set back to network byte order
376 temp = rte_bswap32(thdr->recv_ack);
377 //printf("%s: ackSeqdiff :%d %u\n", __FUNCTION__, ackSeqdiff, temp);
379 temp += abs(ackSeqdiff);
381 temp -= abs(ackSeqdiff);
383 thdr->recv_ack = rte_bswap32(temp);
386 * ftp_alg adjusting SEQ from other end ; SEQ field of onward/egress packet
387 * to be adjusted to the same value of length modified in the payload
388 * Input - pkt, ack diff - delta
389 * Output - None(void)
392 static void ftp_alg_adjust_tcp_seq(struct rte_mbuf *pkt, int16_t ackSeqdiff)
394 /*Since v6 is not supported now*/
395 uint16_t ip_hdr_size_bytes = IPv4_HEADER_SIZE;
396 struct ipv4_hdr *iphdr = (struct ipv4_hdr *)
397 RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START);
398 struct tcp_hdr *thdr = (struct tcp_hdr *)
399 RTE_MBUF_METADATA_UINT32_PTR(pkt,
400 IP_START + ip_hdr_size_bytes);
403 temp = rte_bswap32(thdr->sent_seq);
405 temp -= abs(ackSeqdiff);
407 temp += abs(ackSeqdiff);
409 thdr->sent_seq = rte_bswap32(temp);
412 * ftp_alg adjusting SEQ from other end ; SEQ field of onward/egress packet
413 * to be adjusted to the same value of length modified in the payload;
414 * This function computes the delta and calls adjust_seq for chaging the packet
415 * Input - pkt,Original incoming String, Translated string and corresponding
416 * lengths of the string
417 * Output - Seq Diff between Original and translated string
420 static int ftp_alg_delta_tcp_sequence(
421 struct rte_mbuf *pkt,
423 int16_t existing_tcpSeqdiff,
424 uint16_t old_port_string_length,
425 uint16_t new_port_string_length)
427 int16_t current_sequence_number_delta=0;
428 int16_t final_sequence_number_delta;
429 /*Since v6 is not supported now*/
430 uint16_t ip_hdr_size_bytes = IPv4_HEADER_SIZE;
431 struct ipv4_hdr *iphdr = (struct ipv4_hdr *)
432 RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START);
433 struct tcp_hdr *thdr = (struct tcp_hdr *)
434 RTE_MBUF_METADATA_UINT32_PTR(pkt,
435 IP_START + ip_hdr_size_bytes);
437 * recv_ack and total length first to be chnaged to host byte order
438 * and then do the addition and then set back to network byte order
440 current_sequence_number_delta = (int16_t) (new_port_string_length -
441 old_port_string_length);
442 iphdr->total_length = rte_bswap16(iphdr->total_length);
445 printf("total_length :%u\n", iphdr->total_length);
447 if(current_sequence_number_delta < 0)
448 iphdr->total_length -= abs(current_sequence_number_delta);
450 iphdr->total_length += current_sequence_number_delta;
452 iphdr->total_length = rte_bswap16(iphdr->total_length);
453 if (existing_tcpSeqdiff !=0)
454 ftp_alg_adjust_tcp_seq(pkt,existing_tcpSeqdiff);
455 final_sequence_number_delta= current_sequence_number_delta + existing_tcpSeqdiff;
456 return final_sequence_number_delta;
461 * ftp_alg dpi - this function parses the packet and does the respective
462 * action based on the type PORT or PASV, based on the direction of packet
463 * (Private or Public) This is called from CGNAPT
464 * Input - cgnapt pipeline struct, cgnapt key, pkt, CT ,
465 * position of packet assigned by CT, direction of packet
466 * Output - None - as it calls respective action functions
469 struct pipeline_cgnapt *p_nat,
470 struct pipeline_cgnapt_entry_key *nat_entry_key,
471 struct rte_mbuf *pkt,
472 struct rte_ct_cnxn_tracker *cgnat_cnxn_tracker,
477 * recv_ack and total length first to be chnaged to host byte order
478 * and then do the addition and then set back to network byte order
481 /*entry key to be framed in cgnat and pass it over here*/
482 char *port_cmd_string;
483 char *port_cmd_end_string;
484 char *tcp_header_end;
488 uint16_t private_port_number;
489 uint16_t public_port_number;
490 uint16_t ip1, ip2, ip3, ip4, port1, port2;
491 int16_t tcpSeqdiff = 0;
492 int16_t ackSeqdiff, ackAdjust;
493 uint32_t private_address;
494 uint32_t public_address;
495 uint8_t *bptr_private_address;
496 /* also for PASV string */
497 char port_string[65];
498 char port_string_translated[FTP_MAXIMUM_PORT_STRING_LENGTH];
499 int16_t new_port_string_length = 0;
500 int16_t old_port_string_length;
502 struct cgnapt_table_entry *egress_entry = NULL, *ingress_entry;
504 uint8_t key_direction;
505 /*Since v6 is not supported now*/
506 uint16_t ip_hdr_size_bytes = IPv4_HEADER_SIZE;
508 struct ipv4_hdr *ip_hdr = rte_pktmbuf_mtod_offset(pkt,
509 struct ipv4_hdr *, sizeof(struct ether_hdr));
510 /* TCP and UDP ports at same offset,
511 * just use TCP for offset calculation
513 struct tcp_hdr *thdr = rte_pktmbuf_mtod_offset(pkt, struct tcp_hdr *,
514 (sizeof(struct ether_hdr)+sizeof(struct ipv4_hdr)));
515 uint16_t src_port = rte_bswap16(thdr->src_port);
516 uint16_t dst_port = rte_bswap16(thdr->dst_port);
517 uint8_t proto = ip_hdr->next_proto_id;
518 uint32_t src_addr = rte_bswap32(ip_hdr->src_addr);
519 uint32_t dst_addr = rte_bswap32(ip_hdr->dst_addr);
520 uint32_t tmp_tcp_paylod_size;
523 - src_port & dst_port checking to be moved from cgnat to dpi
524 - For control channel
525 first validation of tcpSeqdiff to be checked
527 ftp_alg_tcp_ack() to be called(this includes PORT
528 response and PASV response ack as well)
531 the port/pasv paramter checkign to be done
535 - remove the ALG entry
536 even if not found(found cases too)
537 - set the bypass flag in the CT session table
543 printf("ftp port number: %d, %d\n", src_port, dst_port);
544 printf("ftp TCP seq num diff: %d\n",
545 cgnat_cnxn_tracker->hash_table_entries[
546 ct_position].tcpSeqdiff);
547 printf("tcp data offset: %d\n",
548 ((thdr->data_off & 0xf0) >> 2));
549 printf("ct position in dpi:%d\n", ct_position);
553 if (src_port == 21 || dst_port == 21)/* Control Channel*/{
554 /* Control Channel Start */
556 * need to look for the port or pasv command. Then have to look for
557 * the IP address and the port address. Then must create a TCP control
558 * block and spoof the port number, and change the ip address, and do
559 * the sequence number setting.
561 /* Handle TCP headers.*/
562 tcp_start = (char *)thdr;
564 /* start of TCP payload */
565 port_cmd_string = (char * )(tcp_start+((thdr->data_off & 0xf0) >> 2));
566 tcp_header_end = port_cmd_string;
568 if (direction == PRIVATE) {
571 printf("In PRIVATE ");
574 cgnat_cnxn_tracker->hash_table_entries[ct_position].seq_client
575 = rte_bswap32(thdr->sent_seq);
576 cgnat_cnxn_tracker->hash_table_entries[ct_position].ack_client
577 = rte_bswap32(thdr->recv_ack);
579 printf("-->Seq_cli:%u, Ack_cli:%u, Len:%4d\n",
580 rte_bswap32(thdr->sent_seq),
581 rte_bswap32(thdr->recv_ack),
582 (rte_bswap16(ip_hdr->total_length) -
583 (((thdr->data_off & 0xf0) >> 4) * 4)) - 20);
588 printf("In PUBLIC ");
590 cgnat_cnxn_tracker->hash_table_entries[ct_position].seq_server
591 = rte_bswap32(thdr->sent_seq);
592 cgnat_cnxn_tracker->hash_table_entries[ct_position].ack_server
593 = rte_bswap32(thdr->recv_ack);
595 printf("<--Seq_cli:%4d, Ack_cli%4d, Len:%4d\n",
596 rte_bswap32(thdr->sent_seq), rte_bswap32(thdr->recv_ack),
597 (ip_hdr->total_length - (((thdr->data_off & 0xf0) >> 2))
602 if (sscanf(port_cmd_string, FTP_PASV_PARAMETER_STRING, &dummy_value,
603 &ip1, &ip2, &ip3, &ip4, &port1, &port2) ==
604 FTP_PASV_PARAMETER_COUNT){
606 snprintf (port_string, sizeof(port_string), FTP_PASV_PARAMETER_STRING, FTP_PASV_RETURN_CODE,
607 ip1, ip2, ip3, ip4, port1, port2);
610 while (port_cmd_string[i] != '\r' && port_cmd_string[i+1] != '\n')
613 i += 2; // now it points to end of port cmd string.
615 old_port_string_length = i;
617 private_port_number = (uint16_t) (port1 * 0x100 + port2);
618 bptr_private_address = (uint8_t *) &private_address;
620 bptr_private_address[3] = (uint8_t) (ip4 & 0x00FF);
621 bptr_private_address[2] = (uint8_t) (ip3 & 0x00FF);
622 bptr_private_address[1] = (uint8_t) (ip2 & 0x00FF);
623 bptr_private_address[0] = (uint8_t) (ip1 & 0x00FF);
625 /* Not needed as got the position from CT*/
627 if (direction == PUBLIC) {
628 /*Client in Private, Server in Public*/
629 /* Not to convert in the payload for PASV resp from Pub side*/
630 /* Only Table creation and no payload modification*/
631 /* DAta Channel also no need to create as it will be done by NAT
632 * when initiated by Client later
634 populate_ftp_alg_entry(private_address, private_port_number);
636 * Bypass ALG flag to be set ,
637 * seqnumber -delta either to be 0 or not needed ,
638 * direction checking for all scenarios
640 cgnat_cnxn_tracker->hash_table_entries[ct_position].
641 server_direction = SERVER_IN_PUBLIC;
642 cgnat_cnxn_tracker->hash_table_entries[ct_position].
643 ftp_session_type= 1; // Passive session type
644 } else if (direction == PRIVATE) {
645 /*Client in Public , Server in Private*/
647 struct pipeline_cgnapt_entry_key data_channel_key;
648 private_address = rte_bswap32(private_address);
649 data_channel_key.ip = private_address;
650 data_channel_key.port = private_port_number;
651 /* to be checked if it can be passed as param from NAT*/
652 data_channel_key.pid = pkt->port;
654 /* add_dynamic_cgnat_entry() */ /* for DAta Channel*/
655 /*Will be getting Private IP and port from Server ,
656 * with that NAPT entry egress and ingress can be added ,
657 * for further data channel communication
660 if (add_dynamic_cgnapt_entry_alg((struct pipeline *)p_nat,
661 &data_channel_key, &egress_entry, &ingress_entry) == 0){
664 printf("Wrong FTP ALG packet\n");
666 //p_nat->invalid_packets |= pkt_mask;
668 p_nat->naptDroppedPktCount++;
670 #ifdef CGNAPT_DEBUGGING
671 p_nat->naptDroppedPktCount4++;
677 tmp_tcp_paylod_size = rte_bswap16(ip_hdr->total_length) -
678 ((thdr->data_off & 0xf0) >> 2) - ip_hdr_size_bytes;
679 cgnat_cnxn_tracker->hash_table_entries[ct_position].
680 tcp_payload_size = tmp_tcp_paylod_size;
683 /*Adding ALG entry , params to be derived from egress entry*/
684 populate_ftp_alg_entry(egress_entry->data.pub_ip,
685 egress_entry->data.pub_port);
687 /* payload modification */
688 new_port_string_length = ftp_alg_modify_payload(egress_entry,
690 port_string_translated, 1);
691 strncpy(tcp_header_end, port_string_translated,
692 strlen(port_string_translated));
693 tcpSeqdiff = ftp_alg_delta_tcp_sequence( pkt, port_string,
694 cgnat_cnxn_tracker->hash_table_entries
695 [ct_position].tcpSeqdiff,
696 old_port_string_length,
697 new_port_string_length);
700 /* same as rte_synproxy_adjust_pkt_length() in ct */
701 ftp_alg_modify_pkt_len(pkt);
703 * Store sequence_number_delta in Session_data structure, also bypass
704 * flag to be set as NO (expecting TCP ack from other end then set the
705 * bypass accordingly , handled earlier in the function
708 cgnat_cnxn_tracker->hash_table_entries[ct_position].
709 alg_bypass_flag = NO_BYPASS;
710 cgnat_cnxn_tracker->hash_table_entries[ct_position].
711 tcpSeqdiff = tcpSeqdiff;
712 cgnat_cnxn_tracker->hash_table_entries[ct_position].
713 server_direction = SERVER_IN_PRIVATE;
714 cgnat_cnxn_tracker->hash_table_entries[ct_position].
715 ftp_session_type = 1; // Passive session type
719 } else if (sscanf(port_cmd_string, FTP_PORT_PARAMETER_STRING,
720 &ip1, &ip2, &ip3, &ip4, &port1, &port2) ==
721 FTP_PORT_PARAMETER_COUNT){
724 static uint8_t port_hit;
725 while (port_cmd_string[i] != '\r' &&
726 port_cmd_string[i+1] != '\n')
729 i += 2; // now it points to end of port cmd string.
731 old_port_string_length = i;
734 printf( " Existing Seq Diff = %d", cgnat_cnxn_tracker->
735 hash_table_entries[ct_position].tcpSeqdiff);
736 printf("FTP ALG: FTP PORT command length: %d\n",
737 old_port_string_length);
740 private_port_number = (uint16_t) (port1 * 0x100 + port2);
743 printf("FTP ALG: private port number before swap: %u\n",
744 private_port_number);
747 bptr_private_address = (uint8_t *) &private_address;
748 bptr_private_address[3] = (uint8_t) (ip4 & 0x00FF);
749 bptr_private_address[2] = (uint8_t) (ip3 & 0x00FF);
750 bptr_private_address[1] = (uint8_t) (ip2 & 0x00FF);
751 bptr_private_address[0] = (uint8_t) (ip1 & 0x00FF);
753 sprintf(port_string, FTP_PORT_PARAMETER_STRING, ip1, ip2,
754 ip3, ip4, port1, port2);
757 printf("FTP ALG: FTP original PORT string: %d,%s\n",
758 (int) strlen(port_string)-2, port_string);
759 printf("prv addr: %x\n", private_address);
763 if (direction == PUBLIC) {
764 /* Client in Public*/
765 /* retreive_cgnat_entry()* for Data Channel*/
766 /* Pub port and ip address to be used for framing key ,
767 * the private phrase is a misnomer
769 struct pipeline_cgnapt_entry_key data_channel_key;
770 data_channel_key.ip = private_address;
771 data_channel_key.port = private_port_number;
772 data_channel_key.pid = 0xffff;
775 cgnat_cnxn_tracker->hash_table_entries[ct_position].
776 server_direction = SERVER_IN_PRIVATE;
777 cgnat_cnxn_tracker->hash_table_entries[ct_position].
778 ftp_session_type= 0; // Active session type
780 /* No payload modificaiton*/
782 printf("<--Seq_cli:%4d, Ack_cli%4d, Len:%4d\n",
783 rte_bswap32(thdr->sent_seq),
784 rte_bswap32(thdr->recv_ack),
785 (ip_hdr->total_length -
786 (((thdr->data_off & 0xf0) >> 2)) - 20));
788 populate_ftp_alg_entry(private_address, private_port_number);
789 } else if (direction == PRIVATE) {
791 /* Client in Private Server in Public*/
792 /* Populate_alg_entry*/
793 /*add_dynamic_cgnapt_entry()*/
794 /* payload modificaion*/
795 struct pipeline_cgnapt_entry_key data_channel_key;
796 private_address = rte_bswap32(private_address);
797 data_channel_key.ip = private_address;
798 data_channel_key.port = private_port_number;
799 /* to be checked if it can be passed as param from NAT*/
800 data_channel_key.pid = pkt->port;
802 /* add_dynamic_cgnat_entry() */ /* for DAta Channel*/
804 * Will be getting Private IP and port from Client ,
805 * with that NAPT entry egress and ingress can be added ,
806 * for further data channel communication
810 if (add_dynamic_cgnapt_entry_alg((struct pipeline *)
811 p_nat, &data_channel_key, &egress_entry,
812 &ingress_entry) == 0){
815 printf("Wrong FTP ALG packet\n");
817 //p_nat->invalid_packets |= pkt_mask;
818 p_nat->naptDroppedPktCount++;
820 #ifdef CGNAPT_DEBUGGING
821 p_nat->naptDroppedPktCount4++;
827 tmp_tcp_paylod_size = rte_bswap16(ip_hdr->total_length) -
828 ((thdr->data_off & 0xf0) >> 2) -
830 cgnat_cnxn_tracker->hash_table_entries[ct_position].
831 tcp_payload_size = tmp_tcp_paylod_size;
832 /*ALG entry add, params to be derived from egress entry*/
835 populate_ftp_alg_entry(egress_entry->data.pub_ip,
836 egress_entry->data.pub_port);
837 /* payload modification */
838 new_port_string_length = ftp_alg_modify_payload(egress_entry,
840 port_string_translated, 0);
841 strncpy(tcp_header_end, port_string_translated,
842 strlen(port_string_translated));
843 tcpSeqdiff = ftp_alg_delta_tcp_sequence( pkt, port_string,
844 cgnat_cnxn_tracker->hash_table_entries
845 [ct_position].tcpSeqdiff,
846 old_port_string_length,
847 new_port_string_length);
849 /* same as rte_synproxy_adjust_pkt_length() in ct */
850 ftp_alg_modify_pkt_len(pkt);
853 * Store sequence_number_delta in Session_data structure ,
854 * also bypass flag to be set as NO
855 * While response from other end is received ,
856 * modify the ack no using reverse sign of sequen
859 cgnat_cnxn_tracker->hash_table_entries[ct_position].
860 alg_bypass_flag = NO_BYPASS;
861 cgnat_cnxn_tracker->hash_table_entries[ct_position].
862 tcpSeqdiff = tcpSeqdiff;
863 cgnat_cnxn_tracker->hash_table_entries[ct_position].
864 server_direction = SERVER_IN_PUBLIC;
865 cgnat_cnxn_tracker->hash_table_entries[ct_position].
866 ftp_session_type = 0; // Active session type
869 printf("<--Seq_cli:%4d, Ack_cli%4d, Len:%4d\n",
870 rte_bswap32(thdr->sent_seq),
871 rte_bswap32(thdr->recv_ack),
872 (ip_hdr->total_length -
873 (((thdr->data_off & 0xf0) >> 2)) - 20));
878 } /* PORT cmd message */
880 if ((ackAdjust=cgnat_cnxn_tracker->hash_table_entries[
881 ct_position].tcpSeqdiff) != 0) {
882 if (direction == PRIVATE) {
884 cgnat_cnxn_tracker->hash_table_entries
885 [ct_position].seq_client !=
886 cgnat_cnxn_tracker->hash_table_entries
887 [ct_position].ack_server) {
889 ftp_alg_adjust_tcp_seq( pkt,ackAdjust);
890 tmp_tcp_paylod_size = rte_bswap16(
891 ip_hdr->total_length) -
892 ((thdr->data_off & 0xf0) >> 2) -
894 cgnat_cnxn_tracker->hash_table_entries
895 [ct_position].tcp_payload_size = tmp_tcp_paylod_size;
897 printf("<--Seq_cli:%4d, Ack_cli%4d, Len:%4d\n",
898 rte_bswap32(thdr->sent_seq),
899 rte_bswap32(thdr->recv_ack),
900 (ip_hdr->total_length -(((thdr->data_off & 0xf0) >> 2))- 20));
904 if (cgnat_cnxn_tracker->hash_table_entries
905 [ct_position].ack_server !=
906 (cgnat_cnxn_tracker->hash_table_entries
907 [ct_position].seq_client +
908 cgnat_cnxn_tracker->hash_table_entries
909 [ct_position].tcp_payload_size)) {
911 ftp_alg_adjust_tcp_ack( pkt,ackAdjust);
913 printf("<--Seq_cli:%4d, Ack_cli%4d, Len:%4d\n",
914 rte_bswap32(thdr->sent_seq),
915 rte_bswap32(thdr->recv_ack),
916 (ip_hdr->total_length -(((thdr->data_off & 0xf0) >> 2))- 20));
921 } /* expected_ack and sequence number updation for PUBLIC dir TCP window */
922 } /* Control Channel End */
924 /*remove the ALG entry, retreival is taken care by rte function */
926 printf("In Data Channel \n");
928 remove_ftp_alg_entry (dst_addr,dst_port);/* remove the ALG entry */
929 cgnat_cnxn_tracker->hash_table_entries[ct_position].alg_bypass_flag = BYPASS;
930 } /* Data Channel End */