Jump to content
 Share

Roy

[C] IPIP Packet Generator - Contains Stats

Recommended Posts

Hey everyone,

 

I just wanted to share some code I've been working on the past couple of days. I made a C program that generates a random amount of packet data based off of the program's arguments (--min and --max). The program encapsulates the packet inside of an outer IP header with the IPIP protocol. Therefore, the endpoint (destination/NAT servers) needs to have an IPIP tunnel. This is similar to my UDP Sender program, but uses AF_PACKET sockets instead, has more in-depth command line options, and uses IPIP. I plan to rewrite my UDP Sender program and make it similar to this program, but it wouldn't use IPIP obviously. That said, this program comes with statistics (e.g. average mbps sent/received, packet loss, packet count, and latency). As of right now, the program puts a timestamp inside of the packet data and parses it when the data is sent back to get the timing of the packet (e.g. the ping). Unfortunately, I wasn't sure of how to do this otherwise unless if I sent the packet, waited for the packet's reply, parsed the packet (e.g. got the timing), and so on which would have been slower in my opinion.

 

Here's the main program's code:

 

SendPackets.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/if.h>
#include <arpa/inet.h>
#include <inttypes.h>
#include <signal.h>
#include <pthread.h>
#include <sys/sysinfo.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <math.h>
#include <getopt.h>

#include "csum.h"

#define MAX_PCKT_LENGTH 0xFFFF  // 65535

static uint8_t cont = 1;
static uint8_t contR = 1;
static uint8_t gwMAC[ETH_ALEN];
static uint64_t sentCount;
static uint64_t recvCount;
static uint64_t totalPing;
static uint64_t minPing;
static uint64_t maxPing;
static uint64_t sentDataTotal;
static uint64_t recvDataTotal;
static int fanoutid;

struct info
{
    char *sIP;
    uint16_t sPort;
    char *dIP;
    char *nIP;
    uint16_t nPort;
    char *interface;
    uint64_t interval;
    uint16_t min;
    uint16_t max;
    int output;
    uint16_t rthreads;
    uint16_t sthreads;
    int help;
} stuff;

static struct option longopts[] =
{
    {"src", required_argument, NULL, 's'},
    {"sport", required_argument, NULL, 1},
    {"dst", required_argument, NULL, 'd'},
    {"nat", required_argument, NULL, 'n'},
    {"nport", required_argument, NULL, 2},
    {"dev", required_argument, NULL, 'i'},
    {"interval", required_argument, NULL, 3},
    {"min", required_argument, NULL, 4},
    {"max", required_argument, NULL, 5},
    {"rthreads", required_argument, NULL, 6},
    {"sthreads", required_argument, NULL, 7},
    {"output", no_argument, &stuff.output, 'o'},
    {"help", no_argument, &stuff.help, 'h'},
    {NULL, 0, NULL, 0}
};

void signHdl(int tmp)
{
    cont = 0;
}

void GetGatewayMAC()
{
    // Command to run.
    char cmd[] = "ip neigh | grep \"$(ip -4 route list 0/0 | cut -d' ' -f3) \" | cut -d' ' -f5 | tr '[a-f]' '[A-F]'";

    // Execute command.
    FILE *fp =  popen(cmd, "r");

    // Check if command is valid.
    if (fp != NULL)
    {
        // Initialize line char.
        char line[18];

        // Get output from command.
        if (fgets(line, sizeof(line), fp) != NULL)
        {
            // Parse output and put it into gwMAC.
            sscanf(line, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &gwMAC[0], &gwMAC[1], &gwMAC[2], &gwMAC[3], &gwMAC[4], &gwMAC[5]);
        }
        
        // Close command.
        pclose(fp);
    }
}

uint16_t randNum(uint16_t min, uint16_t max)
{
    return (rand() % (max - min + 1)) + min;
}


void *threadSendHdl(void *data)
{
    int sockfd;
    struct sockaddr_ll din;

    din.sll_family = PF_PACKET;
    din.sll_ifindex = if_nametoindex(stuff.interface);
    din.sll_protocol = htons(ETH_P_IP);

    if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) < 1)
    {
        perror("socket");

        pthread_exit(NULL);
    }

    struct ifreq ifr;
    
    strcpy(ifr.ifr_name, stuff.interface);

    if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) != 0)
    {
        perror("ioctl");
    }

    memcpy(din.sll_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
    din.sll_halen = ETH_ALEN;

    if (bind(sockfd, (struct sockaddr *)&din, sizeof(din)) < 0)
    {
        perror("bind");
    }
    
    while (cont)
    {
        uint16_t pcktLen = randNum(stuff.min, stuff.max);

        unsigned char buffer[MAX_PCKT_LENGTH];
        memset(buffer, 0, MAX_PCKT_LENGTH);

        struct ethhdr *eth = (struct ethhdr *)buffer;
        eth->h_proto = htons(ETH_P_IP);
        memcpy(eth->h_source, din.sll_addr, ETH_ALEN);
        memcpy(eth->h_dest, gwMAC, ETH_ALEN);

        struct iphdr *oIP = (struct iphdr *) (buffer + sizeof(struct ethhdr));
        oIP->ihl = 5;
        oIP->version = 4;
        oIP->protocol = IPPROTO_IPIP;
        oIP->frag_off = 0;
        oIP->tos = 0x00;
        oIP->ttl = 64;
        oIP->id = 0;
        oIP->saddr = inet_addr(stuff.sIP);
        oIP->daddr = inet_addr(stuff.dIP);
        oIP->tot_len = htons(sizeof(struct iphdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + pcktLen);

        struct iphdr *iIP = (struct iphdr *) (buffer + sizeof(struct ethhdr) + sizeof(struct iphdr));
        iIP->ihl = 5;
        iIP->version = 4;
        iIP->protocol = IPPROTO_UDP;
        iIP->frag_off = 0;
        iIP->tos = 0x00;
        iIP->ttl = 64;
        iIP->id = 0;
        iIP->saddr = inet_addr(stuff.sIP);
        iIP->daddr = inet_addr(stuff.nIP);
        iIP->tot_len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + pcktLen);

        struct udphdr *udp = (struct udphdr *) (buffer + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct iphdr));
        udp->source = htons(stuff.sPort);
        udp->dest = htons(stuff.nPort);
        udp->len = htons(sizeof(struct udphdr) + pcktLen);

        oIP->check = 0;
        oIP->check = ip_fast_csum(oIP, oIP->ihl);
        iIP->check = 0;
        iIP->check = ip_fast_csum(iIP, iIP->ihl);

        struct timeval tv;
        gettimeofday(&tv, NULL);

        unsigned char *header = (unsigned char *)(buffer + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct iphdr) + sizeof(struct udphdr));
        *header = 'l';

        uint64_t *curTime = (uint64_t *)(buffer + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + 1);
        *curTime = 1000000 + tv.tv_sec + tv.tv_usec;

        unsigned char *pcktData = (unsigned char *) (buffer + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + 1 + sizeof(uint64_t));

        for (uint16_t i = 0; i < (pcktLen - sizeof(uint64_t) - 1); i++)
        {
            *pcktData = rand() % 255;
            *pcktData++;
        }

        udp->check = 0;
        udp->check = csum_tcpudp_magic(iIP->saddr, iIP->daddr, sizeof(struct udphdr) + pcktLen, IPPROTO_UDP, csum_partial(udp, sizeof(struct udphdr) + pcktLen, 0));

        uint16_t sent;

        if ((sent = write(sockfd, buffer, ntohs(oIP->tot_len) + sizeof(struct ethhdr))) < 1)
        {
            perror("sent");
        }

        sentDataTotal += sent;
        sentCount++;

        if (stuff.interval > 0)
        {
            usleep(stuff.interval);
        }

        //fprintf(stdout, "Sent %" PRIu16 " bytes of data to IPIP tunnel\n", sent);
    }

    close(sockfd);

    pthread_exit(NULL);
}

void *threadRecvHdl(void *data)
{
    int sockfd;
    struct sockaddr_ll din;
    struct sockaddr_ll rin;
    socklen_t rinLen = sizeof(rin);

    din.sll_family = PF_PACKET;
    din.sll_ifindex = if_nametoindex(stuff.interface);
    din.sll_protocol = htons(ETH_P_IP);

    if ((sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP))) < 1)
    {
        perror("socket");

        pthread_exit(NULL);
    }

    struct ifreq ifr;
    
    strcpy(ifr.ifr_name, stuff.interface);

    if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) != 0)
    {
        perror("ioctl");
    }

    memcpy(din.sll_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
    din.sll_halen = ETH_ALEN;

    if (bind(sockfd, (struct sockaddr *)&din, sizeof(din)) < 0)
    {
        perror("bind");
    }

    int fanoutarg;

    fanoutarg = (fanoutid | (PACKET_FANOUT_HASH << 16));

    if (setsockopt(sockfd, SOL_PACKET, PACKET_FANOUT, &fanoutarg, sizeof(fanoutarg)) < 0)
    {
        perror("setsockopt");

        pthread_exit(NULL);
    }
    
    while (contR)
    {
        unsigned char buffer[MAX_PCKT_LENGTH];
        memset(buffer, 0, MAX_PCKT_LENGTH);

        uint16_t recv;

        if ((recv = recvfrom(sockfd, &buffer, MAX_PCKT_LENGTH, 0, (struct sockaddr *)&rin, &rinLen)) < 1)
        {
            perror("recv");

            continue;
        }

        struct iphdr *oIP = (struct iphdr *) (buffer + sizeof(struct ethhdr));
        
        if (oIP->protocol == IPPROTO_IPIP && oIP->daddr == inet_addr(stuff.sIP))
        {
            struct iphdr *iIP = (struct iphdr *) (buffer + sizeof(struct ethhdr) + sizeof(struct iphdr));

            if (iIP->daddr == inet_addr(stuff.sIP))
            {
                unsigned char *header = (unsigned char *)(buffer + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct iphdr) + sizeof(struct udphdr));

                if (*header != 'l')
                {
                    continue;
                }

                struct timeval tv;
                gettimeofday(&tv, NULL);

                uint64_t nowTime = 1000000 + tv.tv_sec + tv.tv_usec;

                uint64_t *pcktTime = (uint64_t *)(buffer + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + 1);

                uint64_t ping = nowTime - *pcktTime;

                ping /= 1000;

                if (ping > 100000)
                {
                    continue;
                }

                if (stuff.output)
                {
                    fprintf(stdout, "%" PRIu64 "ms\n", ping);
                }

                if (ping > maxPing)
                {
                    maxPing = ping;
                }

                if (ping < minPing || recvCount < 1)
                {
                    minPing = ping;
                }

                totalPing += ping;

                recvDataTotal += recv;
                recvCount++;
                
            }
        }
    }

    close(sockfd);

    pthread_exit(NULL);    
}

int parse_command_line(int argc, char *argv[])
{
    uint8_t pass = 0;

    int c;

    while ((c = getopt_long(argc, argv, "s:d:n:i:oh", longopts, NULL)) != -1)
    {
        switch (c)
        {
            case 's':
                stuff.sIP = optarg;

                break;

            case 1:
                stuff.sPort = atoi(optarg);

                break;

            case 'd':
                stuff.dIP = optarg;

                break;

            case 'n':
                stuff.nIP = optarg;

                break;

            case 2:
                stuff.nPort = atoi(optarg);

                break;

            case 'i':
                stuff.interface = optarg;

                break;

            case 3:
                stuff.interval = strtoll(optarg, NULL, 10);

                break;

            case 4:
                stuff.min = atoi(optarg);

                break;

            case 5:
                stuff.max = atoi(optarg);

                break;

            case 6:
                stuff.rthreads = atoi(optarg);

                break;

            case 7:
                stuff.sthreads = atoi(optarg);

                break;

            case 'o':
                stuff.output = 1;

                break;

            case 'h':
                stuff.help = 1;

                break;

            case '?':
                pass = -1;

                break;
        }
    }

    return pass;
}

int main(int argc, char *argv[])
{
    // Set optional defaults.
    stuff.interval = 1000000;
    stuff.max = 1200;
    stuff.min = 500;
    stuff.rthreads = get_nprocs_conf();
    stuff.sthreads = get_nprocs_conf();

    if (parse_command_line(argc, argv) != 0)
    {
        exit(EXIT_FAILURE);
    }

    if (stuff.help)
    {
        fprintf(stderr, "%s Arguments:\n"
        "-s, --src => Source IP.\n"
        "--sport => Source Port.\n"
        "-d, --dst => Destination IP\n"
        "-n, --nat => NAT IP.\n"
        "--nport => NAT Port.\n"
        "-i, --dev => Network Device Name.\n"
        "--interval => Interval between sent packets.\n"
        "--min => Minimum packet length in bytes.\n"
        "--max => Maximum packet length in bytes.\n"
        "--rthreads => Amount of receiving threads/sockets to spawn.\n"
        "--sthreads => Amount of sending threads/sockets to spawn.\n", argv[0]);

        exit(EXIT_SUCCESS);
    }

    if (stuff.sIP == NULL)
    {
        fprintf(stderr, "Missing --src option for source IP.\n");

        exit(EXIT_FAILURE);
    }

    if (stuff.sPort == 0)
    {
        fprintf(stderr, "Missing --sport option for source port or invalid (0).\n");

        exit(EXIT_FAILURE);
    }

    if (stuff.dIP == NULL)
    {
        fprintf(stderr, "Missing --dst option for destination IP.\n");

        exit(EXIT_FAILURE);
    }

    if (stuff.nIP == NULL)
    {
        fprintf(stderr, "Missing --nat option for NAT IP.\n");

        exit(EXIT_FAILURE);
    }

    if (stuff.nPort == 0)
    {
        fprintf(stderr, "Missing --nport option for NAT port or invalid (0).\n");

        exit(EXIT_FAILURE);
    }

    if (stuff.interface == NULL)
    {
        fprintf(stderr, "Missing --dev option for network device/interface.\n");

        exit(EXIT_FAILURE);
    }

    time_t startTime = time(NULL);

    fanoutid = getpid() & 0xFFFF;

    for (uint16_t i = 0; i < stuff.sthreads; i++)
    {
        pthread_t pid;

        if (pthread_create(&pid, NULL, threadSendHdl, (void *)&stuff) != 0)
        {
            fprintf(stderr, "Error creating sending thread #%d\n", i);
        }
    }

    for (uint16_t i = 0; i < stuff.rthreads; i++)
    {
        pthread_t pid;

        if (pthread_create(&pid, NULL, threadRecvHdl, (void *)&stuff) != 0)
        {
            fprintf(stderr, "Error creating receiving thread #%d\n", i);
        }
    }

    signal(SIGINT, signHdl);
    signal(SIGABRT, signHdl);

    GetGatewayMAC();

    while(cont)
    {
        sleep(1);
    }

    time_t endTime = time(NULL);

    fprintf(stdout, "Cleaning up\n");

    sleep(1);

    contR = 0;

    sleep(1);

    time_t totalTime = endTime - startTime;
    uint64_t avgPing = totalPing / recvCount;

    uint64_t avgSent = sentDataTotal / totalTime;
    uint64_t avgRecv = recvDataTotal / totalTime;

    double pcktLoss = (double) ((double)(sentCount - recvCount) / sentCount);
    pcktLoss *= 100.0;

    avgSent /= 125000;
    avgRecv /= 125000;

    fprintf(stdout, "%" PRIu64 " packets sent and %" PRIu64 " packets received. %" PRIu64 " packets lost. Average ping was %" PRIu64 ". Max ping was %" PRIu64 " and min ping was %" PRIu64 ".\n", sentCount, recvCount, (sentCount - recvCount), avgPing, maxPing, minPing);
    fprintf(stdout, "Total time -> %lu. Average sent => %" PRIu64 " mbps. Average received => %" PRIu64 " mbps. \n", totalTime, avgSent, avgRecv);
    fprintf(stdout, "Packet Loss => %.2f\%%\n", pcktLoss);

    exit(EXIT_SUCCESS);
}

 

Here's the output from ./SendPackets -h for a description of the arguments:

 

root@test02:/home/dev/OutTest# ./SendPackets -h
./SendPackets Arguments:
-s, --src => Source IP.
--sport => Source Port.
-d, --dst => Destination IP
-n, --nat => NAT IP.
--nport => NAT Port.
-i, --dev => Network Device Name.
--interval => Interval between sent packets.
--min => Minimum packet length in bytes.
--max => Maximum packet length in bytes.
--rthreads => Amount of receiving threads/sockets to spawn.
--sthreads => Amount of sending threads/sockets to spawn.

 

Here's an example (with real statistics from my local network):

 

root@test02:/home/dev/OutTest# ./SendPackets --src 10.50.0.3 --sport 27000 --dst 10.50.0.4 -n 10.2.0.5 --nport 27015 -i ens18 --interval 0 --rthreads 4 --sthreads 1
Cleaning up
1899149 packets sent and 1855387 packets received. 43762 packets lost. Average ping was 0. Max ping was 31 and min ping was 0.
Total time -> 77. Average sent => 180 mbps. Average received => 176 mbps.
Packet Loss => 2.30%

 

Here's another program I made that attaches to the IPIP tunnel and sends back replies:

 

AckPackets.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/if.h>
#include <arpa/inet.h>
#include <inttypes.h>
#include <signal.h>
#include <pthread.h>
#include <sys/sysinfo.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <string.h>
#include <sys/time.h>

#include "csum.h"

#define MAX_PCKT_LENGTH 0xFFFF  // 65535

static uint8_t cont = 1;
static uint8_t gwMAC[ETH_ALEN];
static int fanoutid;

struct info
{
    char *interface;
};

void signHdl(int tmp)
{
    cont = 0;
}

void GetGatewayMAC()
{
    // Command to run.
    char cmd[] = "ip neigh | grep \"$(ip -4 route list 0/0 | cut -d' ' -f3) \" | cut -d' ' -f5 | tr '[a-f]' '[A-F]'";

    // Execute command.
    FILE *fp =  popen(cmd, "r");

    // Check if command is valid.
    if (fp != NULL)
    {
        // Initialize line char.
        char line[18];

        // Get output from command.
        if (fgets(line, sizeof(line), fp) != NULL)
        {
            // Parse output and put it into gwMAC.
            sscanf(line, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &gwMAC[0], &gwMAC[1], &gwMAC[2], &gwMAC[3], &gwMAC[4], &gwMAC[5]);
        }
        
        // Close command.
        pclose(fp);
    }
}

void *threadRecvHdl(void *data)
{
    struct info *stuff = (struct info *) data;

    int sockfd, sendSockfd;
    struct sockaddr_ll sin, din;

    if ((sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP))) < 0)
    {
        perror("RecvSocket");

        pthread_exit(NULL);
    }

    struct ifreq ifr;
    strcpy(ifr.ifr_name, stuff->interface);

    if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) != 0)
    {
        perror("ioctl");

        pthread_exit(NULL);
    }

    sin.sll_family = PF_PACKET;
    sin.sll_ifindex = if_nametoindex(stuff->interface);
    sin.sll_protocol = htons(ETH_P_IP);
    memcpy(sin.sll_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
    sin.sll_halen = ETH_ALEN;
    socklen_t sinLen = sizeof(sin);

    if(bind(sockfd, (struct sockaddr *)&sin, sizeof(sin)) != 0)
    {
        perror("bind");

        pthread_exit(NULL);
    }

    int fanoutarg;
    fanoutarg = (fanoutid | (PACKET_FANOUT_HASH << 16));

    if (setsockopt(sockfd, SOL_PACKET, PACKET_FANOUT, &fanoutarg, sizeof(fanoutarg)) < 0)
    {
        perror("setsockopt");

        pthread_exit(NULL);
    }

    if ((sendSockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) < 0)
    {
        perror("SendSocket");

        pthread_exit(NULL);
    }

    din.sll_family = PF_PACKET;
    din.sll_ifindex = sin.sll_ifindex;
    din.sll_protocol = htons(ETH_P_IP);
    memcpy(din.sll_addr, sin.sll_addr, ETH_ALEN);
    din.sll_halen = ETH_ALEN;

    if (bind(sendSockfd, (struct sockaddr *)&din, sizeof(din)) < 0)
    {
        perror("bind");

        pthread_exit(NULL);
    }

    while(cont)
    {
        unsigned char buffer[MAX_PCKT_LENGTH];

        uint16_t recv;

        if ((recv = recvfrom(sockfd, &buffer, MAX_PCKT_LENGTH, 0, (struct sockaddr *)&sin, &sinLen)) < 1)
        {
            perror("recvfrom");

            continue;
        }

        struct iphdr *ip = (struct iphdr *)(buffer);
        struct udphdr *udp = (struct udphdr *)(buffer + sizeof(struct iphdr));
        uint32_t old = ip->saddr;
        ip->saddr = ip->daddr;
        ip->daddr = old;
        ip->check = 0;
        ip->check = ip_fast_csum(ip, ip->ihl);

        udp->check = 0;
        udp->check = csum_tcpudp_magic(ip->saddr, ip->daddr, (recv - sizeof(struct iphdr)), IPPROTO_UDP, csum_partial(udp, (recv - sizeof(struct iphdr)), 0));

        uint16_t sent;

        if ((sent = write(sendSockfd, buffer, recv)) < 1)
        {
            perror("sent");

            continue;
        }

        //fprintf(stdout, "Sent %d packet to host.\n", sent);
    }

    close(sockfd);
    close(sendSockfd);

    pthread_exit(NULL);    
}

int main(int argc, char *argv[])
{
    if (argc < 2)
    {
        fprintf(stderr, "Usage: %s <Interface>\n", argv[0]);

        exit(1);
    }

    fanoutid = getpid() & 0xFFFF;

    struct info stuff;
    stuff.interface = argv[1];

    for (uint8_t i = 0; i < get_nprocs_conf(); i++)
    {
        pthread_t pid;

        if (pthread_create(&pid, NULL, threadRecvHdl, (void *)&stuff) != 0)
        {
            fprintf(stderr, "Error creating receiving thread #%d\n", i);
        }
    }

    signal(SIGINT, signHdl);
    signal(SIGABRT, signHdl);

    GetGatewayMAC();

    while(cont)
    {
        sleep(1);
    }

    fprintf(stdout, "Cleaning up\n");

    sleep(2);

    exit(0);
}

 

Usage for this program is ./AckPackets <Interface Name> (e.g. ./AckPackets ens18).

 

Here's an example of setting up the namespace, IPIP tunnel, and running the AckPackets program:

 

ip netns add ns01
ip tunnel add ipip01 mode ipip remote xxx.xxx.xxx.xxx # Replace xxx.xxx.xxx.xxx with remote IP.
ip link set ipip01 netns ns01
ip netns exec ns01 ip link set lo up
ip netns exec ns01 ip addr add 10.2.0.5/32 dev ipip01
ip netns exec ns01 ip link set ipip01 up
ip netns exec ns01 ip route add default dev ipip01
ip netns exec ns01 ./AckPackets ipip01
...

 

The code doesn't include much documentation or comments at the moment. Once I rewrite my UDP Sender program, I'll be adding many documents and comments to it and I'll release it to GitHub.

 

To build these files, I used GCC like the following:

 

gcc -g SendPackets.c -o SendPackets -lpthread -lm # SendPackets.c program.
gcc -g AckPackets.c -o AckPackets -lpthread # AckPackets.c program.

 

If you have any questions, please let me know!

 

Thank you.

Share this post


Link to post
Share on other sites


4 minutes ago, Leks said:

hi i got question what would i use this for :pogchamp:

If you want to generate packet data to measure performance, this would help, specifically for IPIP traffic. Technically, this can be used as a DoS tool as well, especially if you have the --interval option set to 0 which doesn't wait in-between sending packets. Though, when I rewrite the UDP Sender program, that'll be a lot better for that. I was able to push 600 mbps from one of our machines using this, but that isn't why I made the program. I'm currently seeing how much data and packets our NICs can handle and want to see if that's one of our primary bottlenecks.

 

Thanks.

Share this post


Link to post
Share on other sites


Hidden

I think it would be super interesting. I've always liked C. I mean I do also enjoy the tools that come with higher level languages, and the objects of C++. But sometimes it just gets overly complicated. Something about writing C code is so fun to me.

 

I know you like networking a lot, so I wanna ask. How different is it to write networking code in C compared to other languages?

 

I ask because I have a software dev mindset with C. The speed of the language is appealing. How practical is using C for networking? Is the speed of the language helpful?


I write programs and stuff.

 

If you need to contact me, here is my discord tag: Dustin#6688

 

I am a busy person. So responses may be delayed.

1840045955_Thicco(1).thumb.png.87c04f05633286f3b45b381b4acc4602.png

 

Share this post


Link to post

23 hours ago, _Rocket_ said:

I think it would be super interesting. I've always liked C. I mean I do also enjoy the tools that come with higher level languages, and the objects of C++. But sometimes it just gets overly complicated. Something about writing C code is so fun to me.

 

I know you like networking a lot, so I wanna ask. How different is it to write networking code in C compared to other languages?

 

I ask because I have a software dev mindset with C. The speed of the language is appealing. How practical is using C for networking? Is the speed of the language helpful?

I haven't messed with networking too much in other languages besides PHP and GoLang (once). I think other higher-level languages may make it easier though, but you wouldn't have as much control and it wouldn't be as fast as well. I think the performance advantage and being able to use hooks such as XDP/TC are the biggest appeals to me for C.

 

I plan to get into learning more higher-level languages in the future though and I'll test out the networking side of them. I'll report back to you once I do :) I already have a bit of experience with Java, C++, GoLang, and a few others thankfully.

 

Thanks!

Share this post


Link to post
Share on other sites




×
×
  • Create New...