1

I've been trying and trying to fragment my TCP packets but I havent found any helpful implementation of it. I am familiar with the theory and concepts of fragmentation, have even come across some flags such as IP_PMTUDISC_DONT, IP_PMTUDISC_WANT, and IP_PMTUDISC_DO and set them but the wireshark's capture always showed DF Flag as on.

I've set the MTU of my 'lo' Network Interface to 1500 since I'm using LoopBack Address on both, the server and the client. And I thought that fragmentation will be handled by the Network Layer, but thats not the case I guess... Please help me with fragmentation of the packet.
Here's my code...

Server.cpp

#include <sys/types.h>
#include <sys/socket.h>
#include <iostream>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netdb.h>

int main(){

    struct sockaddr_in serv_addr, cli_addr;
    char buff[255];

    int FileDesc = socket(AF_INET,SOCK_STREAM, 0);
    if(FileDesc < 0){
        perror("Socket Creation Failed. ");
        exit(EXIT_FAILURE);
    }

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(5455);

    if (bind(FileDesc, (const sockaddr*)&serv_addr, sizeof(serv_addr)) < 0){
        perror("Bind Failed.");
        exit(EXIT_FAILURE);
    }

    if (listen(FileDesc, 6) < 0){
        perror("Listen Failed.");
        exit(EXIT_FAILURE);
    }
    
    socklen_t cliLen;
    int AcceptFD = accept(FileDesc, (sockaddr*)&cli_addr, &cliLen);
    if(AcceptFD < 0){
        perror("Accept Failed.");
        exit(EXIT_FAILURE);
    }
 
    //Setting the MTU
    struct ifreq ifr; 
    ifr.ifr_addr.sa_family = AF_INET;//address family
    strncpy(ifr.ifr_name, "lo", sizeof(ifr.ifr_name));//interface name where you want to set the MTU
    ifr.ifr_mtu = 1500; //your MTU size here
    if (ioctl(FileDesc, SIOCGIFMTU, (caddr_t)&ifr) < 0){
        perror("ioctl error.");
        exit(1);
    }
    std::cout << ifr.ifr_ifru.ifru_mtu;
    
    while(1){
      //File Transfer
    }

    close(AcceptFD);
    close(FileDesc);

    return 0;

}

Client.cpp

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <iostream>
#include <unistd.h>
#include <netdb.h>
#include <string.h>
#include <arpa/inet.h>

int main(){

    struct sockaddr_in serv_addr;
    char buffer[255];

    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0){
        perror("Socket Creation Failed.");
        exit(EXIT_FAILURE);
    }

    FILE *fp;
    char *filename = "File.txt";

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    inet_aton("127.0.0.1", &serv_addr.sin_addr);
    serv_addr.sin_port = htons(5455);

    int conn = connect(fd, (const sockaddr*)&serv_addr, sizeof(serv_addr));
    if (conn < 0){
        perror("Connect Failed. ");
        exit(EXIT_FAILURE);
    }

    while(1){
       //File Recieve
    }

    close(fd);
    return 0;

}

This also begs the question, how would I re-assemble my packet back in the same order? Thank youu.

  • you can't. actually you should not worry about this at all. TCP is a stream based protocol. This means it accepts stream of data on one side and returns stream of data on the other side. It is TCP's job to handle dividing the stream into packets of appropriate size and then reconstructing the stream from packets. Also, TCP should figure out what your MTU is and find the appropriate packet size (also called maximum segment size). It is better than the fragmentation at IP layer. – Effie Dec 13 '21 at 08:15
  • what exactly are you trying to achieve? it is hard to tell because the actual code of file transfer code is missing. – Effie Dec 13 '21 at 08:16
  • "how would I re-assemble my packet back in the same order?" you don't, TCP does this for you. – Effie Dec 13 '21 at 08:19
  • here is a reference to the theory of TCP: https://www.computer-networking.info/2nd/html/protocols/tcp.html – Effie Dec 13 '21 at 08:27
  • Thank you @Effie for your comments, actually I am asked by my teacher to show fragmentation happening by examining DF and MF flags in wireshark. So understanding from your comments, fragmentation and defragmentation is handled by TCP and all we do is define an MTU? Also my while loop will basically contain code for sending a file in large checks puposely greater than MTU. I just wanted to know if we could somehow manually fragments the packets. – Awais Nawaz Dec 14 '21 at 08:33
  • i think TCP discovers MTU by itself. I mean it definitelly does, but i do not know how exactly. once this is done, there should be no fragmentation in IP, TCP creates packets so that their eventual size is MTU (smallest of the path). Also, you can have your while loop can just pass data to the socket in arbitrary chunks (well, it would be more efficient if they are big enough, so that syscall is not executed too often). TCP implementation should contain some heuristic on when exactly to send packets. You google for "Nagle's Algorithm". – Effie Dec 14 '21 at 08:40
  • there is a mechanism in TCP that allow you to say something like "send now" (if I am not mistaken this is what PUSH flag is for). However I don't think you ever need to do this in a file transfer case. it would be more suitable for e.g., chat application to signal "send now" after user presses "send". – Effie Dec 14 '21 at 08:41
  • The easiest way to show fragmentation in IP would be to open udp socket and send a udp packet of maximum size. I am not sure how to do this programmatically, but you can use [iperf](https://iperf.fr/) to generate UDP stream that I think will do it for you. TCP is not really good for this. – Effie Dec 14 '21 at 08:46
  • In general, if you for some reason need to do something not the way TCP does it (there are cases where you do), the common way is to use UDP and then implement a custom protocol on top of UDP. UDP is basically send IP packets with port numbers and checksum in them. – Effie Dec 14 '21 at 08:49
  • could you post the exact problem you are trying to solve? It is generally good for Q&A site like stackoverflow if the questions are answered. – Effie Dec 14 '21 at 11:04
  • "You are supposed to create a TCP-based client-server application, and send a very large (more than 5000 bytes) message from TCP server to the TCP client. Such message will be fragmented. Use wireshark to show details of the received IP packet (fragments) on the client side. Also, use netstat to show the established TCP connection between the client and the server. Please submit a single PDF file containing client/server codes and wireshark/netstat screenshots." This is the exact statement of the question, and though I *am* convinced about using UDP and then custom settings on top of it. – Awais Nawaz Dec 14 '21 at 14:05
  • hmmmm. AFAIK TCP is not supposed to work like this. Also, if you are using loopback interface, its MTU is 64k. And if you don't, the card will probably have tcp segmentation offload on, which can also cause your tcp packets to be 64k (and divided into smaller tcp packets in the card itself). So, [here](https://www.cyberciti.biz/faq/how-can-i-setup-the-mtu-for-my-network-interface/) is a commant to set MTU on an interface, maybe it will work for loopback. In this [question](https://stackoverflow.com/questions/3857892/how-to-set-the-maximum-tcp-maximum-segment-size-on-linux) the second answer – Effie Dec 14 '21 at 14:31
  • tells how to set advertised MSS. [Here](https://serverfault.com/questions/751022/forcing-ip-fragmentation-and-reassembly-for-some-traffic-thru-a-vpn-tunnel) are some commands on to how to clear DF bit, but according to the comments they do not work. Maybe if you set the advmss to 5000, mtu for something smaller and then clear the bit it will work. – Effie Dec 14 '21 at 14:33

0 Answers0