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(new_alg_data));
178 //new_alg_data->status = INCOMPLETE;
179 new_alg_data->l4port = rte_bswap16(portid);
180 new_alg_data->ip_address = rte_bswap32(ipaddr);
181 rte_hash_add_key_data(ftp_alg_hash_handle, &alg_key, new_alg_data);
184 // print entire hash table
186 ("\tALG: table update - ip=%d.%d.%d.%d on port=%d\n",
187 (alg_key.ip_address >> 24),
188 ((alg_key.ip_address & 0x00ff0000) >> 16),
189 ((alg_key.ip_address & 0x0000ff00) >> 8),
190 ((alg_key.ip_address & 0x000000ff)), portid);
191 /* print_arp_table(); */
197 * ftp_alg payload modification for PORT and PASV command
198 * Input - cgnapt table entry - for taking the public /translated ip/port ,
199 * incoming PORT/PASV string, Session type - PORT or PASV
200 * Output - Translated string
202 int ftp_alg_modify_payload(
203 struct cgnapt_table_entry *egress_entry,
205 char *port_string_translated, int ftp_session_type)
207 uint32_t transport_ip;
208 uint16_t transport_port;
209 uint16_t tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
210 uint16_t new_port_string_length;
212 uint8_t *bptr_public_address;
214 transport_ip = egress_entry->data.pub_ip;
215 transport_port = egress_entry->data.pub_port;
216 tmp5 = (uint16_t) (transport_port/0x100);
217 tmp6 = (uint16_t) (transport_port % 0x100);
219 transport_ip = rte_bswap32(transport_ip);
221 bptr_public_address = (uint8_t *) &transport_ip;
223 tmp4 = bptr_public_address[3];
224 tmp3 = bptr_public_address[2];
225 tmp2 = bptr_public_address[1];
226 tmp1 = bptr_public_address[0];
228 if (ftp_session_type == 1)
229 sprintf(port_string_translated, FTP_PASV_PARAMETER_STRING,
230 FTP_PASV_RETURN_CODE, tmp1, tmp2, tmp3, tmp4,
233 sprintf(port_string_translated, FTP_PORT_PARAMETER_STRING,
234 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6);
236 printf("FTP ALG: FTP new string: Len:%d %s\n",
237 (uint16_t) strlen(port_string_translated)-2,
238 port_string_translated);
240 printf("FTP non translated PASV string: Len:%d, %s\n",
241 (uint16_t)strlen(port_string)-2, port_string);
242 printf("old strlen:%d new strlen:%d\n",
243 (int)strlen(port_string),
244 (int)strlen(port_string_translated));
247 return(new_port_string_length =
248 (uint16_t) strlen(port_string_translated));
252 * ftp_alg modify packet len (due to change in len of FTP payload )
254 * Output - Length append /Trimmed Pkt
256 static inline void ftp_alg_modify_pkt_len(struct rte_mbuf *pkt)
258 uint16_t pkt_length = 0;
259 int ip_hdr_size_bytes = rte_ct_get_IP_hdr_size(pkt);
260 void *iphdr = RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START);
262 if (ip_hdr_size_bytes == IPv4_HEADER_SIZE) {
263 struct ipv4_hdr *ihdr4 = (struct ipv4_hdr *)iphdr;
264 pkt_length = rte_bswap16(ihdr4->total_length) + ETH_HDR_SIZE;
265 } else if (ip_hdr_size_bytes == IPv6_HEADER_SIZE) {
266 struct ipv6_hdr *ihdr6 = (struct ipv6_hdr *)iphdr;
267 pkt_length = rte_bswap16(ihdr6->payload_len) +
268 IPv6_HEADER_SIZE + ETH_HDR_SIZE;
271 uint16_t mbuf_pkt_length = rte_pktmbuf_pkt_len(pkt);
273 if (pkt_length == mbuf_pkt_length)
276 if (pkt_length < mbuf_pkt_length) {
277 rte_pktmbuf_trim(pkt, mbuf_pkt_length - pkt_length);
281 /* pkt_length > mbuf_pkt_length */
282 rte_pktmbuf_append(pkt, pkt_length - mbuf_pkt_length);
286 * ftp_alg IP HDR size calculation
288 * Output - Length of IP HDR
291 /* same as rte_ct_get_IP_hdr_size()*/
292 uint16_t ftp_alg_get_IP_hdr_size(struct rte_mbuf *pkt)
294 /* NOTE: Only supporting IP headers with no options at this time
295 * so header is fixed size
298 uint8_t hdr_chk = RTE_MBUF_METADATA_UINT8(pkt, IP_START);
299 hdr_chk = hdr_chk >> 4;
301 if (hdr_chk == IP_VERSION_4)
302 return IPv4_HEADER_SIZE;
303 else if (hdr_chk == IP_VERSION_6)
304 return IPv6_HEADER_SIZE;
305 else /* Not IPv4 header with no options, return negative. */
311 * ftp_alg checksum re-computing due to change in payload , uses rte function,
312 * if HW Checksum is supported s/w checksum will be disabled
313 * Input - IP HDR and TCP HDR
314 * Output - Length of IP HDR
316 static void ftp_alg_compute_checksums(
318 struct tcp_hdr *t_hdr)
319 /* same as rte_synproxy_compute_checksums*/
322 * calculate IP and TCP checksums.
323 * Note that both checksum routines require
324 * checksum fields to be set to zero, and the the checksum is in the
325 * correct byte order, so no rte_bswap16 is required.
328 int8_t hdr_chk = rte_ct_ipversion(i_hdr);
331 if (hdr_chk == IP_VERSION_4) {
332 struct ipv4_hdr *i4_hdr = (struct ipv4_hdr *)i_hdr;
333 i4_hdr->hdr_checksum = 0;
335 t_hdr->cksum = rte_ipv4_udptcp_cksum(i4_hdr, t_hdr);
338 printf("cksum %x\n", rte_bswap32(t_hdr->cksum));
341 i4_hdr->hdr_checksum = rte_ipv4_cksum(i4_hdr);
342 } else if (hdr_chk == IP_VERSION_6) {
343 struct ipv6_hdr *i6_hdr = (struct ipv6_hdr *)i_hdr;
345 t_hdr->cksum = rte_ipv6_udptcp_cksum(i6_hdr, t_hdr);
350 * ftp_alg adjusting ACK from other end ;
351 * ACK field of return packet to be adjusted
352 * to the same value of length modified in the payload
353 * Input - pkt, ack diff - delta
354 * Output - None(void)
356 static void ftp_alg_adjust_tcp_ack(struct rte_mbuf *pkt, int16_t ackSeqdiff)
358 /*Since v6 is not supported now*/
359 uint16_t ip_hdr_size_bytes = IPv4_HEADER_SIZE;
360 struct ipv4_hdr *iphdr = (struct ipv4_hdr *)
361 RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START);
362 struct tcp_hdr *thdr = (struct tcp_hdr *)
363 RTE_MBUF_METADATA_UINT32_PTR(pkt,
364 IP_START + ip_hdr_size_bytes);
366 * recv_ack and total length first to be chnaged to host byte order
367 * and then do the addition and then set back to network byte order
370 temp = rte_bswap32(thdr->recv_ack);
371 //printf("%s: ackSeqdiff :%d %u\n", __FUNCTION__, ackSeqdiff, temp);
373 temp += abs(ackSeqdiff);
375 temp -= abs(ackSeqdiff);
377 thdr->recv_ack = rte_bswap32(temp);
380 * ftp_alg adjusting SEQ from other end ; SEQ field of onward/egress packet
381 * to be adjusted to the same value of length modified in the payload
382 * Input - pkt, ack diff - delta
383 * Output - None(void)
386 static void ftp_alg_adjust_tcp_seq(struct rte_mbuf *pkt, int16_t ackSeqdiff)
388 /*Since v6 is not supported now*/
389 uint16_t ip_hdr_size_bytes = IPv4_HEADER_SIZE;
390 struct ipv4_hdr *iphdr = (struct ipv4_hdr *)
391 RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START);
392 struct tcp_hdr *thdr = (struct tcp_hdr *)
393 RTE_MBUF_METADATA_UINT32_PTR(pkt,
394 IP_START + ip_hdr_size_bytes);
397 temp = rte_bswap32(thdr->sent_seq);
399 temp -= abs(ackSeqdiff);
401 temp += abs(ackSeqdiff);
403 thdr->sent_seq = rte_bswap32(temp);
406 * ftp_alg adjusting SEQ from other end ; SEQ field of onward/egress packet
407 * to be adjusted to the same value of length modified in the payload;
408 * This function computes the delta and calls adjust_seq for chaging the packet
409 * Input - pkt,Original incoming String, Translated string and corresponding
410 * lengths of the string
411 * Output - Seq Diff between Original and translated string
414 static int ftp_alg_delta_tcp_sequence(
415 struct rte_mbuf *pkt,
417 int16_t existing_tcpSeqdiff,
418 uint16_t old_port_string_length,
419 uint16_t new_port_string_length)
421 int16_t current_sequence_number_delta=0;
422 int16_t final_sequence_number_delta;
423 /*Since v6 is not supported now*/
424 uint16_t ip_hdr_size_bytes = IPv4_HEADER_SIZE;
425 struct ipv4_hdr *iphdr = (struct ipv4_hdr *)
426 RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START);
427 struct tcp_hdr *thdr = (struct tcp_hdr *)
428 RTE_MBUF_METADATA_UINT32_PTR(pkt,
429 IP_START + ip_hdr_size_bytes);
431 * recv_ack and total length first to be chnaged to host byte order
432 * and then do the addition and then set back to network byte order
434 current_sequence_number_delta = (int16_t) (new_port_string_length -
435 old_port_string_length);
436 iphdr->total_length = rte_bswap16(iphdr->total_length);
439 printf("total_length :%u\n", iphdr->total_length);
441 if(current_sequence_number_delta < 0)
442 iphdr->total_length -= abs(current_sequence_number_delta);
444 iphdr->total_length += current_sequence_number_delta;
446 iphdr->total_length = rte_bswap16(iphdr->total_length);
447 if (existing_tcpSeqdiff !=0)
448 ftp_alg_adjust_tcp_seq(pkt,existing_tcpSeqdiff);
449 final_sequence_number_delta= current_sequence_number_delta + existing_tcpSeqdiff;
450 return final_sequence_number_delta;
455 * ftp_alg dpi - this function parses the packet and does the respective
456 * action based on the type PORT or PASV, based on the direction of packet
457 * (Private or Public) This is called from CGNAPT
458 * Input - cgnapt pipeline struct, cgnapt key, pkt, CT ,
459 * position of packet assigned by CT, direction of packet
460 * Output - None - as it calls respective action functions
463 struct pipeline_cgnapt *p_nat,
464 struct pipeline_cgnapt_entry_key *nat_entry_key,
465 struct rte_mbuf *pkt,
466 struct rte_ct_cnxn_tracker *cgnat_cnxn_tracker,
471 * recv_ack and total length first to be chnaged to host byte order
472 * and then do the addition and then set back to network byte order
475 /*entry key to be framed in cgnat and pass it over here*/
476 char *port_cmd_string;
477 char *port_cmd_end_string;
478 char *tcp_header_end;
482 uint16_t private_port_number;
483 uint16_t public_port_number;
484 uint16_t ip1, ip2, ip3, ip4, port1, port2;
486 int16_t ackSeqdiff, ackAdjust;
487 uint32_t private_address;
488 uint32_t public_address;
489 uint8_t *bptr_private_address;
490 /* also for PASV string */
491 char port_string[FTP_MAXIMUM_PORT_STRING_LENGTH];
492 char port_string_translated[FTP_MAXIMUM_PORT_STRING_LENGTH];
493 int16_t new_port_string_length;
494 int16_t old_port_string_length;
496 struct cgnapt_table_entry *egress_entry, *ingress_entry;
498 uint8_t key_direction;
499 /*Since v6 is not supported now*/
500 uint16_t ip_hdr_size_bytes = IPv4_HEADER_SIZE;
502 struct ipv4_hdr *ip_hdr = rte_pktmbuf_mtod_offset(pkt,
503 struct ipv4_hdr *, sizeof(struct ether_hdr));
504 /* TCP and UDP ports at same offset,
505 * just use TCP for offset calculation
507 struct tcp_hdr *thdr = rte_pktmbuf_mtod_offset(pkt, struct tcp_hdr *,
508 (sizeof(struct ether_hdr)+sizeof(struct ipv4_hdr)));
509 uint16_t src_port = rte_bswap16(thdr->src_port);
510 uint16_t dst_port = rte_bswap16(thdr->dst_port);
511 uint8_t proto = ip_hdr->next_proto_id;
512 uint32_t src_addr = rte_bswap32(ip_hdr->src_addr);
513 uint32_t dst_addr = rte_bswap32(ip_hdr->dst_addr);
514 uint32_t tmp_tcp_paylod_size;
517 - src_port & dst_port checking to be moved from cgnat to dpi
518 - For control channel
519 first validation of tcpSeqdiff to be checked
521 ftp_alg_tcp_ack() to be called(this includes PORT
522 response and PASV response ack as well)
525 the port/pasv paramter checkign to be done
529 - remove the ALG entry
530 even if not found(found cases too)
531 - set the bypass flag in the CT session table
537 printf("ftp port number: %d, %d\n", src_port, dst_port);
538 printf("ftp TCP seq num diff: %d\n",
539 cgnat_cnxn_tracker->hash_table_entries[
540 ct_position].tcpSeqdiff);
541 printf("tcp data offset: %d\n",
542 ((thdr->data_off & 0xf0) >> 2));
543 printf("ct position in dpi:%d\n", ct_position);
547 if (src_port == 21 || dst_port == 21)/* Control Channel*/{
548 /* Control Channel Start */
550 * need to look for the port or pasv command. Then have to look for
551 * the IP address and the port address. Then must create a TCP control
552 * block and spoof the port number, and change the ip address, and do
553 * the sequence number setting.
555 /* Handle TCP headers.*/
556 tcp_start = (char *)thdr;
558 /* start of TCP payload */
559 port_cmd_string = (char * )(tcp_start+((thdr->data_off & 0xf0) >> 2));
560 tcp_header_end = port_cmd_string;
562 if (direction == PRIVATE) {
565 printf("In PRIVATE ");
568 cgnat_cnxn_tracker->hash_table_entries[ct_position].seq_client
569 = rte_bswap32(thdr->sent_seq);
570 cgnat_cnxn_tracker->hash_table_entries[ct_position].ack_client
571 = rte_bswap32(thdr->recv_ack);
573 printf("-->Seq_cli:%u, Ack_cli:%u, Len:%4d\n",
574 rte_bswap32(thdr->sent_seq),
575 rte_bswap32(thdr->recv_ack),
576 (rte_bswap16(ip_hdr->total_length) -
577 (((thdr->data_off & 0xf0) >> 4) * 4)) - 20);
582 printf("In PUBLIC ");
584 cgnat_cnxn_tracker->hash_table_entries[ct_position].seq_server
585 = rte_bswap32(thdr->sent_seq);
586 cgnat_cnxn_tracker->hash_table_entries[ct_position].ack_server
587 = rte_bswap32(thdr->recv_ack);
589 printf("<--Seq_cli:%4d, Ack_cli%4d, Len:%4d\n",
590 rte_bswap32(thdr->sent_seq), rte_bswap32(thdr->recv_ack),
591 (ip_hdr->total_length - (((thdr->data_off & 0xf0) >> 2))
596 if (sscanf(port_cmd_string, FTP_PASV_PARAMETER_STRING, &dummy_value,
597 &ip1, &ip2, &ip3, &ip4, &port1, &port2) ==
598 FTP_PASV_PARAMETER_COUNT){
600 sprintf (port_string, FTP_PASV_PARAMETER_STRING, FTP_PASV_RETURN_CODE,
601 ip1, ip2, ip3, ip4, port1, port2);
604 while (port_cmd_string[i] != '\r' && port_cmd_string[i+1] != '\n')
607 i += 2; // now it points to end of port cmd string.
609 old_port_string_length = i;
611 private_port_number = (uint16_t) (port1 * 0x100 + port2);
612 bptr_private_address = (uint8_t *) &private_address;
614 bptr_private_address[3] = (uint8_t) (ip4 & 0x00FF);
615 bptr_private_address[2] = (uint8_t) (ip3 & 0x00FF);
616 bptr_private_address[1] = (uint8_t) (ip2 & 0x00FF);
617 bptr_private_address[0] = (uint8_t) (ip1 & 0x00FF);
619 /* Not needed as got the position from CT*/
621 if (direction == PUBLIC) {
622 /*Client in Private, Server in Public*/
623 /* Not to convert in the payload for PASV resp from Pub side*/
624 /* Only Table creation and no payload modification*/
625 /* DAta Channel also no need to create as it will be done by NAT
626 * when initiated by Client later
628 populate_ftp_alg_entry(private_address, private_port_number);
630 * Bypass ALG flag to be set ,
631 * seqnumber -delta either to be 0 or not needed ,
632 * direction checking for all scenarios
634 cgnat_cnxn_tracker->hash_table_entries[ct_position].
635 server_direction = SERVER_IN_PUBLIC;
636 cgnat_cnxn_tracker->hash_table_entries[ct_position].
637 ftp_session_type= 1; // Passive session type
638 } else if (direction == PRIVATE) {
639 /*Client in Public , Server in Private*/
641 struct pipeline_cgnapt_entry_key data_channel_key;
642 private_address = rte_bswap32(private_address);
643 data_channel_key.ip = private_address;
644 data_channel_key.port = private_port_number;
645 /* to be checked if it can be passed as param from NAT*/
646 data_channel_key.pid = pkt->port;
648 /* add_dynamic_cgnat_entry() */ /* for DAta Channel*/
649 /*Will be getting Private IP and port from Server ,
650 * with that NAPT entry egress and ingress can be added ,
651 * for further data channel communication
654 if (add_dynamic_cgnapt_entry_alg((struct pipeline *)p_nat,
655 &data_channel_key, &egress_entry, &ingress_entry) == 0){
658 printf("Wrong FTP ALG packet\n");
660 //p_nat->invalid_packets |= pkt_mask;
662 p_nat->naptDroppedPktCount++;
664 #ifdef CGNAPT_DEBUGGING
665 p_nat->naptDroppedPktCount4++;
671 tmp_tcp_paylod_size = rte_bswap16(ip_hdr->total_length) -
672 ((thdr->data_off & 0xf0) >> 2) - ip_hdr_size_bytes;
673 cgnat_cnxn_tracker->hash_table_entries[ct_position].
674 tcp_payload_size = tmp_tcp_paylod_size;
676 /*Adding ALG entry , params to be derived from egress entry*/
677 populate_ftp_alg_entry(egress_entry->data.pub_ip,
678 egress_entry->data.pub_port);
679 /* payload modification */
680 new_port_string_length = ftp_alg_modify_payload(egress_entry,
682 port_string_translated, 1);
683 strncpy(tcp_header_end, port_string_translated,
684 strlen(port_string_translated));
685 tcpSeqdiff = ftp_alg_delta_tcp_sequence( pkt, port_string,
686 cgnat_cnxn_tracker->hash_table_entries
687 [ct_position].tcpSeqdiff,
688 old_port_string_length,
689 new_port_string_length);
691 /* same as rte_synproxy_adjust_pkt_length() in ct */
692 ftp_alg_modify_pkt_len(pkt);
694 * Store sequence_number_delta in Session_data structure, also bypass
695 * flag to be set as NO (expecting TCP ack from other end then set the
696 * bypass accordingly , handled earlier in the function
699 cgnat_cnxn_tracker->hash_table_entries[ct_position].
700 alg_bypass_flag = NO_BYPASS;
701 cgnat_cnxn_tracker->hash_table_entries[ct_position].
702 tcpSeqdiff = tcpSeqdiff;
703 cgnat_cnxn_tracker->hash_table_entries[ct_position].
704 server_direction = SERVER_IN_PRIVATE;
705 cgnat_cnxn_tracker->hash_table_entries[ct_position].
706 ftp_session_type = 1; // Passive session type
710 } else if (sscanf(port_cmd_string, FTP_PORT_PARAMETER_STRING,
711 &ip1, &ip2, &ip3, &ip4, &port1, &port2) ==
712 FTP_PORT_PARAMETER_COUNT){
715 static uint8_t port_hit;
716 while (port_cmd_string[i] != '\r' &&
717 port_cmd_string[i+1] != '\n')
720 i += 2; // now it points to end of port cmd string.
722 old_port_string_length = i;
725 printf( " Existing Seq Diff = %d", cgnat_cnxn_tracker->
726 hash_table_entries[ct_position].tcpSeqdiff);
727 printf("FTP ALG: FTP PORT command length: %d\n",
728 old_port_string_length);
731 private_port_number = (uint16_t) (port1 * 0x100 + port2);
734 printf("FTP ALG: private port number before swap: %u\n",
735 private_port_number);
738 bptr_private_address = (uint8_t *) &private_address;
739 bptr_private_address[3] = (uint8_t) (ip4 & 0x00FF);
740 bptr_private_address[2] = (uint8_t) (ip3 & 0x00FF);
741 bptr_private_address[1] = (uint8_t) (ip2 & 0x00FF);
742 bptr_private_address[0] = (uint8_t) (ip1 & 0x00FF);
744 sprintf(port_string, FTP_PORT_PARAMETER_STRING, ip1, ip2,
745 ip3, ip4, port1, port2);
748 printf("FTP ALG: FTP original PORT string: %d,%s\n",
749 (int) strlen(port_string)-2, port_string);
750 printf("prv addr: %x\n", private_address);
754 if (direction == PUBLIC) {
755 /* Client in Public*/
756 /* retreive_cgnat_entry()* for Data Channel*/
757 /* Pub port and ip address to be used for framing key ,
758 * the private phrase is a misnomer
760 struct pipeline_cgnapt_entry_key data_channel_key;
761 data_channel_key.ip = private_address;
762 data_channel_key.port = private_port_number;
763 data_channel_key.pid = 0xffff;
766 cgnat_cnxn_tracker->hash_table_entries[ct_position].
767 server_direction = SERVER_IN_PRIVATE;
768 cgnat_cnxn_tracker->hash_table_entries[ct_position].
769 ftp_session_type= 0; // Active session type
771 /* No payload modificaiton*/
773 printf("<--Seq_cli:%4d, Ack_cli%4d, Len:%4d\n",
774 rte_bswap32(thdr->sent_seq),
775 rte_bswap32(thdr->recv_ack),
776 (ip_hdr->total_length -
777 (((thdr->data_off & 0xf0) >> 2)) - 20));
779 populate_ftp_alg_entry(private_address, private_port_number);
780 } else if (direction == PRIVATE) {
782 /* Client in Private Server in Public*/
783 /* Populate_alg_entry*/
784 /*add_dynamic_cgnapt_entry()*/
785 /* payload modificaion*/
786 struct pipeline_cgnapt_entry_key data_channel_key;
787 private_address = rte_bswap32(private_address);
788 data_channel_key.ip = private_address;
789 data_channel_key.port = private_port_number;
790 /* to be checked if it can be passed as param from NAT*/
791 data_channel_key.pid = pkt->port;
793 /* add_dynamic_cgnat_entry() */ /* for DAta Channel*/
795 * Will be getting Private IP and port from Client ,
796 * with that NAPT entry egress and ingress can be added ,
797 * for further data channel communication
801 if (add_dynamic_cgnapt_entry_alg((struct pipeline *)
802 p_nat, &data_channel_key, &egress_entry,
803 &ingress_entry) == 0){
806 printf("Wrong FTP ALG packet\n");
808 //p_nat->invalid_packets |= pkt_mask;
809 p_nat->naptDroppedPktCount++;
811 #ifdef CGNAPT_DEBUGGING
812 p_nat->naptDroppedPktCount4++;
818 tmp_tcp_paylod_size = rte_bswap16(ip_hdr->total_length) -
819 ((thdr->data_off & 0xf0) >> 2) -
821 cgnat_cnxn_tracker->hash_table_entries[ct_position].
822 tcp_payload_size = tmp_tcp_paylod_size;
823 /*ALG entry add, params to be derived from egress entry*/
825 populate_ftp_alg_entry(egress_entry->data.pub_ip,
826 egress_entry->data.pub_port);
827 /* payload modification */
828 new_port_string_length = ftp_alg_modify_payload(egress_entry,
830 port_string_translated, 0);
831 strncpy(tcp_header_end, port_string_translated,
832 strlen(port_string_translated));
833 tcpSeqdiff = ftp_alg_delta_tcp_sequence( pkt, port_string,
834 cgnat_cnxn_tracker->hash_table_entries
835 [ct_position].tcpSeqdiff,
836 old_port_string_length,
837 new_port_string_length);
838 /* same as rte_synproxy_adjust_pkt_length() in ct */
839 ftp_alg_modify_pkt_len(pkt);
842 * Store sequence_number_delta in Session_data structure ,
843 * also bypass flag to be set as NO
844 * While response from other end is received ,
845 * modify the ack no using reverse sign of sequen
848 cgnat_cnxn_tracker->hash_table_entries[ct_position].
849 alg_bypass_flag = NO_BYPASS;
850 cgnat_cnxn_tracker->hash_table_entries[ct_position].
851 tcpSeqdiff = tcpSeqdiff;
852 cgnat_cnxn_tracker->hash_table_entries[ct_position].
853 server_direction = SERVER_IN_PUBLIC;
854 cgnat_cnxn_tracker->hash_table_entries[ct_position].
855 ftp_session_type = 0; // Active session type
858 printf("<--Seq_cli:%4d, Ack_cli%4d, Len:%4d\n",
859 rte_bswap32(thdr->sent_seq),
860 rte_bswap32(thdr->recv_ack),
861 (ip_hdr->total_length -
862 (((thdr->data_off & 0xf0) >> 2)) - 20));
867 } /* PORT cmd message */
869 if ((ackAdjust=cgnat_cnxn_tracker->hash_table_entries[
870 ct_position].tcpSeqdiff) != 0) {
871 if (direction == PRIVATE) {
873 cgnat_cnxn_tracker->hash_table_entries
874 [ct_position].seq_client !=
875 cgnat_cnxn_tracker->hash_table_entries
876 [ct_position].ack_server) {
878 ftp_alg_adjust_tcp_seq( pkt,ackAdjust);
879 tmp_tcp_paylod_size = rte_bswap16(
880 ip_hdr->total_length) -
881 ((thdr->data_off & 0xf0) >> 2) -
883 cgnat_cnxn_tracker->hash_table_entries
884 [ct_position].tcp_payload_size = tmp_tcp_paylod_size;
886 printf("<--Seq_cli:%4d, Ack_cli%4d, Len:%4d\n",
887 rte_bswap32(thdr->sent_seq),
888 rte_bswap32(thdr->recv_ack),
889 (ip_hdr->total_length -(((thdr->data_off & 0xf0) >> 2))- 20));
893 if (cgnat_cnxn_tracker->hash_table_entries
894 [ct_position].ack_server !=
895 (cgnat_cnxn_tracker->hash_table_entries
896 [ct_position].seq_client +
897 cgnat_cnxn_tracker->hash_table_entries
898 [ct_position].tcp_payload_size)) {
900 ftp_alg_adjust_tcp_ack( pkt,ackAdjust);
902 printf("<--Seq_cli:%4d, Ack_cli%4d, Len:%4d\n",
903 rte_bswap32(thdr->sent_seq),
904 rte_bswap32(thdr->recv_ack),
905 (ip_hdr->total_length -(((thdr->data_off & 0xf0) >> 2))- 20));
910 } /* expected_ack and sequence number updation for PUBLIC dir TCP window */
911 } /* Control Channel End */
913 /*remove the ALG entry, retreival is taken care by rte function */
915 printf("In Data Channel \n");
917 remove_ftp_alg_entry (dst_addr,dst_port);/* remove the ALG entry */
918 cgnat_cnxn_tracker->hash_table_entries[ct_position].alg_bypass_flag = BYPASS;
919 } /* Data Channel End */