1
\$\begingroup\$

So I am getting packets from TUN interface and after that processing the packet, and then try to send correct TCP handshake response message.

It does handle sequence and ack sequence handling but That needs to be reviewed with useful feed back. Also the tcp checksum code is I am bit unsure about

This is main function file test.c

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <signal.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <net/route.h>
//#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <linux/if_tunnel.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/select.h>
#include <unistd.h>


#include "ttools.h"

static char *_progname = NULL;
static int  _tun_fd = -1;
static int  _udp_fd = -1;
static int  _do_exit = 0;
static ip4_addr_t _remote_ip = 0L;

//char * get_ip_str(uint32_t addr,char *str);



int print_header(char *buf,char *buf_1);
int debug(const char *format, ...)
{
    va_list ap;
    int ret = -1;
    
    va_start(ap, format);
    ret = vprintf(format, ap);
    va_end(ap);
    
    return ret; 
}
static void usage(void)
{
    debug("Usage: %s tun-ip remote-ip\n", _progname);
    debug("Example: %s  172.16.0.1  10.10.10.10\n", _progname);
}
void close_tun_iface(void)
{
    int close_ret = -1;
#if 0
    if (ioctl( fd, TUNSETPERSIST, 0 ) < 0) {
        /*debug("Error - cannot delete tun device: %s\n", strerror(errno));*/
        return;
    }
#endif
    if (_tun_fd != -1) {
        close_ret = close(_tun_fd);
        _tun_fd = -1;
        debug("Closing tun iface: [%d] %s.\n", close_ret, strerror(errno));
    }
}
int set_mtu(struct ifreq *ifr_tun, int sock, unsigned int mtu)
{
    /* Set the MTU of the tap interface */
    ifr_tun->ifr_mtu = mtu;
    if (ioctl(sock, SIOCSIFMTU, ifr_tun) < 0)  {
        debug("%s: SIOCSIFMTU: %s\n", _progname, strerror(errno));
        return -1;
    }

    debug("MTU was set to %d\n", mtu);
    return 0;
}
int set_ip(struct ifreq *ifr_tun, int sock, ip4_addr_t ip4)
{
    struct sockaddr_in addr;

    /* set the IP of this end point of tunnel */
    memset( &addr, 0, sizeof(addr) );
    addr.sin_addr.s_addr = ip4; /*network byte order*/
    addr.sin_family = AF_INET;
    memcpy( &ifr_tun->ifr_addr, &addr, sizeof(struct sockaddr) );

    if ( ioctl(sock, SIOCSIFADDR, ifr_tun) < 0) {
        debug("%s: socket SIOCSIFADDR: %s\n", _progname, strerror(errno));
        close(sock);
        return -1;
    }

    return 0;
}

int open_tun_iface(ip4_addr_t local_ip4)
{
    struct ifreq ifr_tun;
    int fd = -1;
    int sock = -1;
  //  int mtu = VPN_PATH_MTU;

    if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
        debug("%s: Cannot open /dev/net/tun: %s. Do modprobe tun; lsmod\n", _progname, strerror(errno));
        return -1;
    }

    memset( &ifr_tun, 0, sizeof(ifr_tun) );
    ifr_tun.ifr_flags = IFF_TUN;// | IFF_NO_PI;
    if ((ioctl(fd, TUNSETIFF, (void *)&ifr_tun)) < 0) {
        debug("%s: TUNSETIFF error: %s\n", _progname, strerror(errno));
        close(fd);
        return -1;
    }

#if 0
    if (ioctl(fd, TUNSETPERSIST, 1) < 0) {
        debug("%s: TUNSETPERSIST error: %s\n", _progname, strerror(errno));
        close(fd);
        return -1;
    }
#endif

    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) {
        debug("%s: Cannot open udp socket: %s\n", _progname, strerror(errno) );
        close(fd);
        return -1;
    }

    if (set_ip(&ifr_tun, sock, local_ip4) < 0) {
        close(fd);
        close(sock);
        return -1;
    }


    if (ioctl(sock, SIOCGIFFLAGS, &ifr_tun) < 0) {
        debug("%s: SIOCGIFFLAGS: %s\n", _progname, strerror(errno));
        close(fd);
        close(sock);
        return -1;
    }

    ifr_tun.ifr_flags |= IFF_UP;
    ifr_tun.ifr_flags |= IFF_RUNNING;

    if (ioctl(sock, SIOCSIFFLAGS, &ifr_tun) < 0)  {
        debug("%s: SIOCSIFFLAGS: %s\n", _progname, strerror(errno));
        close(fd);
        close(sock);
        return -1;
    }


    /*mtu = get_if_mtu("eth0", sock);*/
  /*  mtu = path_mtu_to_ip(_remote_ip, 32);
    if (mtu <= 0) {
        mtu = INTERNET_MTU;
    }

    if (mtu + VPN_OVERHEAD > VPN_MIN_MTU)
        mtu -= VPN_OVERHEAD;

    if (0 != set_mtu(&ifr_tun, sock, mtu)) {
        close(fd);
        close(sock);
        return -1;
    }
*/
    debug("** TUN opened: %s\n", ifr_tun.ifr_name);
    close(sock);

    return fd;
}
int open_udp_socket(void)
{
    int sock = -1;

    sock = socket(PF_INET, SOCK_DGRAM, 0);
    if (sock > 0) {
        int ret = -1;
        struct sockaddr_in myaddr;
        int optval = 1;

        setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval) );

        myaddr.sin_family = AF_INET;
        myaddr.sin_port = htons(VPN_UDP_PORT);
        myaddr.sin_addr.s_addr = INADDR_ANY;    /* automatically fill with my IP*/
        memset(&(myaddr.sin_zero), '\0', 8);    /* zero the rest of the struct*/

        ret = bind(sock, (struct sockaddr*)&myaddr, sizeof(myaddr));
        if (ret < 0) {
            debug("%s: bind() %s\n", _progname, strerror(errno));
            close(sock);
            sock = -1;
        }
    } else {
        debug("%s: socket() %s\n", _progname, strerror(errno));
    }

    return sock;
}
static void set_signal(int signo, void (*handler)(int))
{
    struct sigaction sa;

    memset(&sa, 0, sizeof(sa));

    sa.sa_handler = (void (*)(int))handler;
#ifdef SA_INTERRUPT
    sa.sa_flags = SA_INTERRUPT;
#endif
    sigaction(signo, &sa, NULL);
}
static void
sigexit(int signo)
{
    _do_exit = 1;
}
char * get_ip_str_1(uint32_t addr,char *str)
{
    struct sockaddr_in address1;
    address1.sin_addr.s_addr = addr;
    memcpy(str,inet_ntoa(address1.sin_addr),18);
    return str;

}

int print_header_(char *buf,char *buf_1)
{
    char ip_source[18]={0};
    char ip_dest[18]={0};
    struct iphdr *iph=(struct iphdr *)buf;
    printf("*Receiving | source = %s , dest = %s\n",get_ip_str_1(iph->saddr,ip_source),get_ip_str_1(iph->daddr,ip_dest));
    struct iphdr *ip=(struct iphdr *)buf_1;
    ip->saddr=iph->daddr;
    ip->daddr=iph->saddr;
    printf("*Sending | source = %s , dest = %s\n",get_ip_str_1(ip->saddr,ip_source),get_ip_str_1(ip->daddr,ip_dest));
    return 0;

    
}
void * receiver(void *data)
{

    //struct sockaddr_in cliaddr = {0};
    int recvlen = -1;
    int writelen = -1;
    //socklen_t clilen = sizeof(cliaddr);

    while (!_do_exit) {
        //recvlen = rrecvfrom(_udp_fd, buf, sizeof(buf), 0, (struct sockaddr*)&cliaddr, &clilen);
        //recvlen = rrecvfrom(_tun_fd, buf, sizeof(buf), 0, (struct sockaddr*)&cliaddr, &clilen);
        char buf[VPN_MAX_MTU] = {0};
        char buf_1[VPN_MAX_MTU] = {0};
        memset(buf,0,VPN_MAX_MTU);
        memset(buf_1,0,VPN_MAX_MTU);

        char *str_source=malloc(18);
        char *str_dest=malloc(18);
        memset(str_source,0,18);
        memset(str_dest,0,18);
       
        recvlen=read(_tun_fd,buf,VPN_MAX_MTU);
       
    print_header(buf,buf_1);
        debug("SR:%04d\n", recvlen);
        
       print_header_(buf,buf_1); 
        struct iphdr *ip=(struct iphdr *)buf_1;
       printf("***Sending source = %s dest = %s...\n",get_ip_str_1(ip->saddr,str_source),get_ip_str_1(ip->daddr,str_dest));
       
        if (recvlen > 0) {
            writelen = write(_tun_fd, buf_1, recvlen);
            printf("WOW wrote tcp response\n\n");
            debug("TW:%04d\n", writelen);
            if (writelen < 0) {
                debug("%s: rwrite() %s [%d]\n", _progname, strerror(errno), errno);
               //break;
            }
        } else if (recvlen < 0) {
            debug("%s: rrecvfrom() %s\n", _progname, strerror(errno));
           // break;
        } else if (recvlen == 0) {
            //break;
        }
    }

    debug("** Receiver ending.\n");
    pthread_exit(NULL);
}


int main(int argc, char **argv)
{
    const char *tun_ip = NULL;    /*virtual*/
    const char *remote_ip = NULL; /*physical*/
    ip4_addr_t local_ip4 = 0L;
    pthread_t tid_recv;//, tid_trans;
        void *thread_ret = NULL;
        

    _progname = argv[0];
    if (argc != 3) 
    {
        usage();
        exit(EXIT_FAILURE);
    }

    tun_ip = argv[1];
    remote_ip = argv[2];
    if (0 >= inet_pton(AF_INET, tun_ip, &local_ip4)) 
    {
       debug("%s: invalid IP address %s\n", _progname, tun_ip);
       exit(EXIT_FAILURE);
    }
    
    set_signal(SIGINT,  sigexit);
    set_signal(SIGQUIT, sigexit);

    
    _tun_fd = open_tun_iface(local_ip4);
    if (_tun_fd < 0 ) 
    {
        exit(EXIT_FAILURE);
    }

    _udp_fd = open_udp_socket();
    if (_udp_fd < 0 ) 
    {
        exit(EXIT_FAILURE);
    }
    
    if (0 >= inet_pton(AF_INET, tun_ip, &local_ip4)) 
    {
        debug("%s: invalid IP address %s\n", _progname, tun_ip);
        exit(EXIT_FAILURE);
        }
    if (0 >= inet_pton(AF_INET, remote_ip, &_remote_ip)) 
    {
        debug("%s: invalid IP address %s\n", _progname, remote_ip);
        exit(EXIT_FAILURE);
    }
    
    pthread_create(&tid_recv,  NULL, receiver,    NULL);
    
     while (!_do_exit)
        sleep(1);

    debug("** Shutting down...\n");
    close_tun_iface();
    shutdown(_udp_fd, 2); _udp_fd = -1;
    pthread_join(tid_recv,  &thread_ret);

    return 0;
}

This is ttools.h

#ifndef _TTOOLS_H_
#define _TTOOLS_H_


#include <sys/socket.h>
#include <linux/types.h>
#include <linux/if_ether.h>
#include <sys/time.h>
#include <stdarg.h>
#include <unistd.h>




/*Sometimes missing*/
#ifndef ETH_FCS_LEN
#  define ETH_FCS_LEN (4)
#endif

#define ETH_MAX_PAYLOAD (ETH_DATA_LEN) /*Max MTU*/
#define ETH_OVERHEAD    (ETH_HLEN/*14*/ + ETH_FCS_LEN)

/*Actually of variable size. see also: linux/ip.h: struct iphdr*/
#define IP_HDR_SZ    (20)
#define IP_OVERHEAD  IP_HDR_SZ

#define UDP_HDR_SZ   (8)
#define UDP_OVERHEAD UDP_HDR_SZ

#define VPN_UDP_PORT (11223)

#define VPN_OVERHEAD (ETH_OVERHEAD + IP_OVERHEAD + UDP_OVERHEAD)
#define VPN_PATH_MTU (ETH_MAX_PAYLOAD - VPN_OVERHEAD)
#define VPN_MIN_MTU  (68)
#define INTERNET_MTU (576)

#define VPN_MAX_MTU      (2*ETH_MAX_PAYLOAD)


/*Network byte order assumed.*/
typedef u_int32_t ip4_addr_t;

int path_mtu_to(const char *ip4, unsigned int num_tries);
int path_mtu_to_ip(ip4_addr_t ip4, unsigned int num_tries);

/* Sample usage: mtu = get_if_mtu("eth0", sock); */
int get_if_mtu(const char *iface, int sock);

int debug(const char *format, ...);

/*
 * Calls restarted on EINTR
 */
int rselect(int n, fd_set *rds, fd_set *wds, fd_set *eds,
            struct timeval *tout);
ssize_t rread(int fd, void *buf, int len);
ssize_t rwrite(int fd, const void *buf, int len);
ssize_t rsend(int sock, const char *buf, int len, int flags);
ssize_t rrecv(int sock, char *buf, int len, int flags);
ssize_t rrecvfrom(int s, void *buf, size_t len, int flags,
                  struct sockaddr *from, socklen_t *fromlen);
ssize_t rsendto(int  s,  const void *buf, size_t len, int flags,
                const struct sockaddr *to, socklen_t tolen);
ssize_t rrecvmsg(int socket, struct msghdr *message, int flags);
int print_header(char *buf,char *buf_1);


#endif /*_TTOOLS_H_*/

and this is tcp packet processing middle code tcp_work.c with header2.h

tcp_work.c ...

#include <stdio.h>
#include "ttools.h"

#include <netinet/tcp.h>
#include <malloc.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
//#include "header.h"
//#include <netinet/ip.h>
#include <string.h>

#include "header2.h"
char * get_ip_str(uint32_t addr,char *str)
{
    struct sockaddr_in address1;
    address1.sin_addr.s_addr = addr;
    memcpy(str,inet_ntoa(address1.sin_addr),18);
    return str;

}


uint16_t csum(const void *data, const int length)
{
    /*  Checksum Algorithm (http://www.microhowto.info/howto/calculate_an_internet_protocol_checksum_in_c.html)
    1. Set the sum to 0,
    2. Pad the data to an even number of bytes,
    3. Reinterpret the data as a sequence of 16-bit unsigned integers that are
        in network byte order,
    4. Calculate the sum of the integers, subtracting 0xffff whenever
        the sum => 0x10000, and
    5. Calculate the bitwise complement of the sum and set it as the checksum.
    */
    printf("[[[[[[[[%d]]]]]]]]\n",length);
    uint16_t *accumalator = (uint16_t *)data;
    uint64_t sum = 0;

    /* Take care of the first 16-bit even blocks */
    for (int i = 0; i < length/2; ++i) {
        sum += *(accumalator+i);
        if (sum >= 0x10000) {
            sum -= 0xffff;
        }
    }

    /* Handle the ending partial block */
    if (length % 2 != 0) {
        accumalator = accumalator+ length/2; /* Point accumalator to the end block */
        uint16_t end_block = 0;
        memcpy(&end_block, accumalator, sizeof(length));
        sum += ntohs(end_block);
        if (sum >= 0x10000) {
            sum -= 0xffff;
        }
    }
    /* Return the one's complement of the checksum in network byte order */
    return htons(~sum);
}

uint16_t tcp_chksum(struct iphdr1 *snd_iph, struct tcphdr1 *snd_tcph)
{
    struct psuedo_header psh;

    psh.src_addr = snd_iph->saddr;
    psh.dst_addr = snd_iph->daddr;
    psh.rsvd = 0;
    psh.proto = IPPROTO_TCP;
    psh.len_tcp = htons(sizeof(struct tcphdr1));    /* No options, and no data */

    int pseudogram_size = sizeof(struct tcphdr1) + sizeof(struct psuedo_header);
    char *pseudogram = malloc(pseudogram_size);

    memcpy(pseudogram, (char *)&psh, sizeof(struct psuedo_header));
    memcpy(pseudogram + sizeof(struct psuedo_header), snd_tcph, sizeof(struct tcphdr1));

//return(htons(csum(pseudogram, pseudogram_size)));
    return (htons(csum(snd_tcph, sizeof(struct  tcphdr1)) + csum(&psh, sizeof(struct psuedo_header))));
}

int print_header(char *buf,char *buf_1)
{
    struct iphdr1 *iph=(struct iphdr1 *)buf;
    struct iphdr1 *ip=(struct iphdr1 *)buf_1;
    //memset(ip->saddr,0,sizeof(uint32_t));
    //memset(ip->daddr,0,sizeof(uint32_t));
    //memcpy(&ip->saddr,iph->daddr,sizeof(uint32_t));
    //memcpy(&ip->daddr,iph->saddr,sizeof(uint32_t));
    ip->saddr=iph->daddr;
    ip->daddr=iph->saddr;
    printf("ip id = %d\n",(unsigned  int)iph->id);
    char *str=malloc(18);
    char *str1=malloc(18);
    if(str==NULL)
    {
        printf("heap\n");
        exit(0);
    }
    if(str1==NULL)
    {
        printf("heap\n");
        exit(0);
    }
    

    memset(str,0,18);
    memset(str1,0,18);
    printf("Receiving | source ip = %s dest ip = %s\n",get_ip_str(iph->saddr,str),get_ip_str(iph->daddr,str1));
    
    memset(str,0,18);
    memset(str1,0,18);
    printf("Sending | source ip = %s dest ip = %s\n",get_ip_str(ip->saddr,str),get_ip_str(ip->daddr,str1));

    memset(str,0,18);
    memset(str1,0,18);


    str1=NULL;
    str=NULL;
    free(str1);
    free(str);



    //int some
    populate_ip_some(iph,ip);
    


    ///change_int_val((unsigned int)5,(ip->ihl));
    ip->ihl=5;
    printf("*header length = %d\n",(unsigned int)iph->ihl);

    //printf("flags = %x\n",iph->flags);
    printf("header length = %d\n",(unsigned int)iph->ihl);
    printf("total length = %d\n",ntohs(iph->tot_len));
    printf("protocol = %d\n",(unsigned int)iph->protocol);
    printf("IP checksum = %d\n",(iph->check));
    printf("{{{{%d}}}",(uint16_t)csum(iph,sizeof(*iph)));
    iph->check=0;
    int16_t i=0;

    i=csum(iph,sizeof(*iph));

    iph->check=htons(i);
    printf("After IP checksum = %d\n",htons(i));
    i=csum(ip,sizeof(*ip));
    ip->check=i;
    printf("ttl = %d\n",(unsigned int)iph->ttl);
    printf("tos = %d\n",iph->tos);
    printf("version = %d\n",iph->version);
    printf("frag offset = %d\n",iph->frag_off);

    printf("TCP\n");
    int iphdrlen = iph->ihl*4;
    printf("iphdrlen = %d\n",iphdrlen);
    struct tcphdr1 *tcph=(struct tcphdr1 *)(buf+iphdrlen);
    struct tcphdr1 *tcp=(struct tcphdr1 *)(buf_1+iphdrlen);
    printf("Received TCP flags syn = %d ack = %d fin = %d\n",tcph->syn,tcph->ack,tcph->fin);
    int tcp_flag= populate_tcp_port(tcph,tcp);
    tcp_flag=populate_tcp_flags(tcph,tcp);
    if(tcp_flag)
    {
            printf("\n\n");
            printf("sending TCP flags syn = %d ack = %d fin = %d \n",tcp->syn,tcp->ack,tcp->fin);
            printf("recieved sequence %d\n",ntohs(tcph->seq));
            int tcp_flag=populate_tcp_some(tcph,tcp);
            //char hh[50]={0};
        //  printf("sending source = %s | dest = %s",get_ip_str(ip->saddr,hh),get_ip_str(ip->daddr,str));
            printf("\n\n");
            if(tcp_flag)
            {
                return 1;
            }

    }

    printf("TCP checksum = %d\n",(tcph->check));
    tcph->check=0;
    uint16_t ch=tcp_chksum(iph,tcph);
    printf("after TCP checksum =  %d\n",((ch)));//firs try then add ntohs then two ntohs
    printf("source port %d dest port = %d\n",ntohs(tcph->source),ntohs(tcph->dest));
    printf("sequence number = %d\n",ntohl(tcph->seq));
    printf("acknowledge number = %d\n",ntohl(tcph->ack_seq));
    printf("data offset = %d\n",(unsigned int)tcph->doff);
    printf("FLAGS TCP\n");
    printf("sync = %d\nack = %d\nrst = %d\nfin = %d\npsh = %d urg = %d\n",(unsigned int)tcph->syn,(unsigned int)tcph->ack,(unsigned int)tcph->rst,(unsigned int)tcph->fin,(unsigned int)tcph->psh,(unsigned int)tcph->urg);
    printf("window = %d \n",ntohs(tcph->window));
    printf("__________________________________________\n");
    return 0;

}

this is header2.h

#include <arpa/inet.h>
#include <string.h>
typedef uint32_t tcp_seq;
struct psuedo_header
{
    uint32_t    src_addr;
    uint32_t    dst_addr;
    uint8_t     rsvd;
    uint8_t     proto;
    uint16_t    len_tcp;
};



struct iphdr1
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ihl:4;//5
unsigned int version:4;//4
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int version:4;
unsigned int ihl:4;
#else
# error "Please fix <bits/endian.h>"
#endif
uint8_t tos;//0
uint16_t tot_len;
uint16_t id;
uint16_t frag_off;//64
uint8_t ttl;//64
uint8_t protocol;//6
uint16_t check;
uint32_t saddr;
uint32_t daddr;
/*The options start here. */
};


struct tcphdr1
{
    __extension__ union
    {
      struct
      {
    uint16_t th_sport;  /* source port */
    uint16_t th_dport;  /* destination port */
    tcp_seq th_seq;     /* sequence number */
    tcp_seq th_ack;     /* acknowledgement number */
# if __BYTE_ORDER == __LITTLE_ENDIAN
    uint8_t th_x2:4;    /* (unused) */
    uint8_t th_off:4;   /* data offset */
# endif
# if __BYTE_ORDER == __BIG_ENDIAN
    uint8_t th_off:4;   /* data offset */
    uint8_t th_x2:4;    /* (unused) */
# endif
    uint8_t th_flags;
# define TH_FIN 0x01
# define TH_SYN 0x02
# define TH_RST 0x04
# define TH_PUSH    0x08
# define TH_ACK 0x10
# define TH_URG 0x20
    uint16_t th_win;    /* window */
    uint16_t th_sum;    /* checksum */
    uint16_t th_urp;    /* urgent pointer */
      };
      struct
      {
    uint16_t source;
    uint16_t dest;
    uint32_t seq;
    uint32_t ack_seq;
# if __BYTE_ORDER == __LITTLE_ENDIAN
    uint16_t res1:4;
    uint16_t doff:4;
    uint16_t fin:1;
    uint16_t syn:1;
    uint16_t rst:1;
    uint16_t psh:1;
    uint16_t ack:1;
    uint16_t urg:1;
    uint16_t res2:2;
# elif __BYTE_ORDER == __BIG_ENDIAN
    uint16_t doff:4;
    uint16_t res1:4;
    uint16_t res2:2;
    uint16_t urg:1;
    uint16_t ack:1;
    uint16_t psh:1;
    uint16_t rst:1;
    uint16_t syn:1;
    uint16_t fin:1;
# else
#  error "Adjust your <bits/endian.h> defines"
# endif
    uint16_t window;
    uint16_t check;
    uint16_t urg_ptr;
      };
    };
};

int populate_ip_hdr_1(struct iphdr1 *o1,struct iphdr1 *o2)
{
    (o2)->saddr=o1->daddr;
    (o2)->daddr=o1->saddr;
//  memcpy((char *)&o2->saddr,&o1->daddr,sizeof(uint32_t));
    //memcpy((char *    )&o2->daddr,&o1->saddr,sizeof(uint32_t));
    return 1;

}

int populate_ip_some(struct iphdr1 *o1,struct iphdr1 *o2)
{
    o2->ihl=o1->ihl;
    o2->version=o1->version;
    o2->tos=o1->tos;
    o2->tot_len=o1->tot_len;
    o2->id=htons(ntohs(o1->id)+1);
    o2->frag_off=o1->frag_off;
    o2->ttl=o1->ttl;
    o2->protocol=o1->protocol;
    o2->check=0;
    return 1;

}
int populate_tcp_port(struct tcphdr1 *o1,struct tcphdr1 *o2)
{
    o2->source=o1->dest;
    o2->dest=o1->source;
    return 1;
}

int populate_tcp_flags(struct tcphdr1 *o1,struct tcphdr1 *o2)
{
    printf("\n\n");
    if(o1->syn==1 && o1->ack==0)
    {
        printf("syn received\n\n");
        o2->syn=1;
        o2->ack=1;
        o2->rst=0;
        o2->fin=0;
        return 1;
    }
    if(o1->syn ==0 && o1->ack==1)
    {
        printf("ack received\n\n");
        o2->syn=0;
        o2->ack=0;
        o2->rst=0;
        o2->fin=0;
        return 1;
    }
    if(o1->syn==0 && o1->fin==1)
    {
        printf("fin received\n\n");
        o2->syn=0;
        o2->ack=1;
        o2->fin=0;
        o2->rst=0;
        return 1;
    }

    return 1;


}
uint32_t *i;
int x=0;
int populate_tcp_some(struct tcphdr1 *o1,struct tcphdr1 *o2)
{
    if(x==0)
    {
        i=malloc(sizeof(int)*100);
        if(i==NULL)
        {printf("heap\n");exit(0);}
    }
    *(i+x)=x;
    o2->seq=htons(*(i+x));
    printf("\n\nsending sequnce %d...\n\n",ntohs(*(i+x)));
  uint32_t host=ntohs(o1->seq);
    o2->ack_seq=htons(host);
    printf("sending ack_sequence %d\n",ntohs(o2->ack_seq));
    o2->doff=o1->doff;

    o2->res1=o1->res1;
    o2->window=o1->window;
    o2->check=0;
    o2->urg_ptr=o1->urg_ptr;
    x++;



    return 1;
}

char * get_ip_str(uint32_t addr,char *str);
int print_header(char *buf,char *buf_1);

this is makefile

#
#
#

CC = gcc
LD = ld

UDPTUN_FILES   = test.c tcp_work.c
UDPTUN_OBJ     = $(UDPTUN_FILES:%.c=%.o)
UDPTUN_CFLAGS  = -g -Wall -pthread -save-temps  
UDPTUN_LDFLAGS = -L. -lpthread



PATHMTU_CFLAGS  = -g -Wall -pthread -save-temps 
PATHMTU_LDFLAGS = -L. -lpthread


all: udptun

udptun: tcp_work.c test.c ttools.h 
    $(CC) $(PATHMTU_CFLAGS) $(PATHMTU_LDFLAGS) -o $@ $+ $(UDPTUN_LDFLAGS)


.IGNORE: clean
clean:
    rm udptun *.o *.i *.s core*


backup: clean
    #rm -rf /media/disk/vpn/*
    cd .. && cp -pR vpn /media/disk/
    sync
    ls -l /media/disk/vpn/*

refresh: 
    cp -pR /media/disk/vpn/* . 

u run the program like

  root@fwd:/home/fawad/Desktop/tun/test# ./udptun 192.168.10.2 192.168.10.3
\$\endgroup\$
2
  • \$\begingroup\$ correctly tcp client connect fails \$\endgroup\$
    – user786
    Dec 25, 2021 at 10:37
  • \$\begingroup\$ first ip in run command will be set as ip of tun interface \$\endgroup\$
    – user786
    Dec 25, 2021 at 10:49

1 Answer 1

1
\$\begingroup\$

Use struct iphdr and struct tcphdr

Most operating systems come with header files that provide you with struct iphdr and struct tcphdr, so you don't need to have your own copies. And especially since your code only runs on Linux, why not just #include <netinet/ip.h> and <netinet/tcp.h> and be done with it?

If you do want your own copies for some reason, then don't assume that #include <arpa/inet.h> is enough to provide all the type and macro definitions you are using; ensure you #include <stdint.h> and <bits/endian.h>, and provide your own typedefs for things like tcp_seq.

Code organization and consistency

The organization of your code looks very messy. Some of the things I see are:

  • Why is there both print_header() and print_header_()?
  • Why do some header files contain function definitions?
  • Why do you have a declaration for rwrite(), but you only use write() in your code?
  • Why use printf() in some places but debug() in others?
  • Why cast &sph to char * but pass snd_tcph without a cast to memcpy()?
  • There's also inconsistency in how you indent code and your use of whitespace. Consider using a code formatting tool like indent to reformat your code.
  • Why is some code commented out? I strongly suggest you remove unused code. Use a revision control system like git to manage the history of your code.
  • Why are you opening a UDP socket when you are not using that at all?

All this makes the code hard to review, and I'm sure it makes it harder for you to develop this code as well. Make sure your code is tidy.

Memory leaks

There are lots of places where you call malloc(), but only two occurences of free(). This means you are leaking a lot of memory. Make sure you fix all memory leaks. Tools like Valgrind or your compiler's -fsantize=leak option might help you find leaks.

Note that in many cases, you don't need to use malloc() at all. If you have a small, temporary buffer, just declare an array on the stack instead. For example, in receiver(), just write:

char str_source[18] = "";
char str_dest[18] = "";

The above lines avoid the need for malloc(), memset() and free().

Unnecessary initialization of buffers

There is a lot of unnecessary memset() calls in your code. Consider:

char buf[VPN_MAX_MTU] = {0};
memset(buf,0,VPN_MAX_MTU);

The first line already initializes buf to be filled with zeroes, so the memset() in the second line is redundant. But even the initialization is not necessary, since you are overwriting the buffer anyway in this line:

recvlen=read(_tun_fd,buf,VPN_MAX_MTU);

Use const and static where possible

I see some functions are marked static and some pointer parameters are made const, but you can use const and static in much more places. Doing this will help the compiler optimize the code better, and avoids accidental mistakes.

Unnecessary use of threads

I don't see why you create a receiver thread and then just sleep forever in the main thread until someone presses control-C. You can instead just call receiver() directly from main(). Also, I wouldn't install signal handlers, the default handlers will kill the process, but this will automatically close all filedescriptors.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.