Question

I have, as requested, included the code in its entirety so that you can test it. Keep in mind that this is nowhere near completion, but should be able to send and recieve packets through a stable tcp connection.

When I run it I get:

./bunny -i 84.49.76.98 -p 80 -o 79.161.200.48 -t 80

Raw packet reader created
Waiting 1 second for packet reader thread to settle down...

socket() - Using SOCK_RAW and TCP protocol is OK.
Socketoptions OK.

and then it just hangs. I've also used strace and that gave me (only including the last bit where it stopped):

setsockopt(4, SOL_IP, IP_HDRINCL, [1], 4) = 0
write(1, "Socketoptions OK.\n", 18Socketoptions OK.
)     = 18
sendto(4, "", 0, 0, {sa_family=AF_INET, sin_port=htons(63239), sin_addr=inet_addr("84.49.76.98")}, 16) = 0
close(4)                                = 0
futex(0x7f4c07bf89d0, FUTEX_WAIT, 3278, NULLsendto(4, "", 0, 0, {sa_family=AF_INET, sin_port=htons(63239), sin_addr=inet_addr("84.49.76.98")}, 16) = 0
close(4)                                = 0

and the system monitor says the program is sleeping, and gives futex_wait_queue_me.

Could this be down to a memory leak somewhere causing too many calls to futex?

#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
#include <pcap.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>

#define VERSION "1.0"
#define PCKT_LEN 8192

/* Prototypes */    
int sock;   
void run();
void capture();
void usage(); 
in_addr_t sip;
in_addr_t dip;
char *dstip = 0;
int s_seq;
int sport;
int dport;              

struct pseudo {
struct in_addr sourceip;
struct in_addr destip;
unsigned char placeholder;
unsigned char protocol;
unsigned char tcp_len;
struct tcphdr tcp;
};

struct ipheader {

unsigned char       iph_ihl:5, 
                    iph_ver:4;
unsigned char       iph_tos;
unsigned short int  iph_len;
unsigned short int  iph_id;
unsigned char       iph_flags;
unsigned short int  iph_offset;
unsigned char       iph_ttl;
unsigned char       iph_protocol;
unsigned short int  iph_chksum;
unsigned int        iph_sourceip;
unsigned int        iph_destip;
};

struct tcpheader {
unsigned short int  tcph_sourceport;
unsigned short int  tcph_destport;
unsigned int        tcph_seqnum;
unsigned int        tcph_acknum;
unsigned char       tcph_reserved:4, tcph_offset:4;
unsigned char       tcph_flags;
unsigned short int  tcph_win;
unsigned short int  tcph_chksum;
unsigned short int  tcph_urgptr;
};



/* Checksum */
unsigned short checksum (unsigned short *pac, int len)
{ 
unsigned long sum;
for (sum = 0; len > 0; len--)
    sum += *pac++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return(~sum);
}               

/* Checksum TCP */
unsigned short checksum_tcp (unsigned short len, unsigned short sourceip[], 
                            unsigned short destip[], unsigned short buf[])
{
unsigned char protocol = 6;
unsigned long sum;
int nleft;
unsigned short *w;

sum = 0;
nleft = len;
w=buf;

while(nleft > 1)
    {
        sum += *w++;
        nleft -= 2;
    }
if(nleft > 0)
    {
        sum += *w&ntohs(0xFF00);
    }

sum += sourceip[0];
sum += sourceip[1];
sum += destip[0];
sum += destip[1];
sum += htons(len);
sum += htons(protocol);

sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);

sum = ~sum;
return ((unsigned short) sum);
}

int main(int argc,char **argv)
{
int c;

/* Are we in root? */   
if(geteuid() !=0)
    {
        printf("Root access is required to run this program.\n\n");
        exit(0);        
    }   

while (1)
    {
        static struct option long_options[] =
            {
                /* Options */
            {"send",       no_argument,       0, 's'}, /* args s, r and f have no function yet */
            {"receive",    no_argument,       0, 'r'},
            {"file",       required_argument, 0, 'f'}, 
            {"destip",     required_argument, 0, 'i'},
            {"destport",   required_argument, 0, 'p'},
            {"sourceip",   required_argument, 0, 'o'},
            {"sourceport", required_argument, 0, 't'},
            {0, 0, 0, 0}
            };

           int option_index = 0;

           c = getopt_long (argc, argv, "srf:d:i:p:o:t:",
                        long_options, &option_index);

                      /* Detect the end of the options. */
            if (c == -1)
                break;

            switch (c)
                {
                    case 0: /* If this option set a flag, do nothing else now. */
                            if (long_options[option_index].flag != 0)
                            break;
                                printf ("option %s", long_options[option_index].name);
                            if (optarg)
                                printf (" with arg %s", optarg);
                                printf ("\n");
                            break;

                    case 's': puts ("option -s\n");
                              break;
                    case 'r': puts ("option -r\n");
                              break;
                    case 'f': printf ("option -f with value `%s'\n", optarg);
                              break;
                    case 'i': dip = inet_addr(optarg);
                              dstip = optarg;
                              break;
                    case 'p': dport = htons(atoi(optarg)); 
                              /* Add handling of bad/non number input here */
                              break;
                    case 'o': sip = inet_addr(optarg);
                              break;
                    case 't': sport = htons(atoi(optarg));
                              break;
                    case '?': /* Error message printed */
                              break;
                    default:  abort ();
                }
    }

/* Print any remaining command line arguments (not options). */
if (optind < argc)
    {
        printf ("\nNon-option ARGV-elements: ");
while (optind < argc)
        printf ("%s ", argv[optind++]);
        putchar ('\n');
    }

/* check if all mandatory options are set and for unknown arguments */
/* This really needs changing... */
if (dip, sip, dport, sport == 0)
    {
        usage();
        return (-1);
    }

/* change */

pthread_t tid_pr;

if (pthread_create(&tid_pr, NULL, capture, NULL) != 0) {
    fprintf(stderr, "can't create raw packet reader: %s\n", strerror(errno));
    exit(1);
}
printf("\nRaw packet reader created\nWaiting 1 second for packet reader thread to settle down...\n\n");
sleep(1);

run();  

pthread_join(tid_pr, NULL);

getchar ();
exit (0);

}

int send_syn(unsigned int sourceip, unsigned int destip, unsigned short sourceport,
            unsigned short destport)
{
const int one = 1;
char buffer[PCKT_LEN];
struct sockaddr_in sin;
struct ipheader *ip;
struct tcpheader *tcp;

ip = (struct ipheader *) buffer;
tcp = (struct tcpheader *) buffer + ip->iph_ihl *4;

/* IP attributes */
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16;
ip->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader);
ip->iph_id = htons(54321);
ip->iph_offset = 0;
ip->iph_ttl = 64;
ip->iph_protocol = IPPROTO_TCP;
ip->iph_chksum = 0;                     
ip->iph_sourceip = sip;
ip->iph_destip = dip;
ip->iph_chksum = checksum ((unsigned short *) buffer, (sizeof (struct 
                            ipheader )+ sizeof (struct tcpheader)));            
/* TCP attributes */
tcp->tcph_sourceport = sport;
tcp->tcph_destport = dport;         
tcp->tcph_seqnum = htonl(1);        /* ADD SEQ NUM THINGY */
tcp->tcph_offset = 5;
tcp->tcph_flags = TH_SYN;
tcp->tcph_win = htons(32767);
tcp->tcph_chksum = 0; 
tcp->tcph_urgptr = 0;
tcp->tcph_chksum = (unsigned short) checksum_tcp((unsigned short) (ip->iph_len - ip->iph_ihl *4), (unsigned short *) &ip->iph_sourceip,
                    (unsigned short *) &ip->iph_destip, (unsigned short *) &tcp);       

/* Address family */ 
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ip->iph_destip;

/* Send */
if (sendto(sock, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
    {
        fprintf(stderr, "\nCan't send packet\n");
        return (-1);
    }               
else
        printf("Packet sent to %d", dip); 

        close(sock);
}           

int send_syn_ack(unsigned int sourceip, unsigned int destip, unsigned short sourceport,
            unsigned short destport, unsigned long s_seq)   
{
const int one = 1;
char buffer[PCKT_LEN];
struct sockaddr_in sin;
struct ipheader *ip;
struct tcpheader *tcp;

ip = (struct ipheader *) buffer;
tcp = (struct tcpheader *) buffer + ip->iph_ihl *4;

/* IP attributes */
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16;
ip->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader);
ip->iph_id = htons(54321);
ip->iph_offset = 0;
ip->iph_ttl = 64;
ip->iph_protocol = IPPROTO_TCP;
ip->iph_chksum = 0;                     
ip->iph_sourceip = sip;
ip->iph_destip = dip;
ip->iph_chksum = checksum ((unsigned short *) buffer, (sizeof (struct 
                            ipheader )+ sizeof (struct tcpheader)));            
/* TCP attributes */
tcp->tcph_sourceport = sport;
tcp->tcph_destport = dport;         
tcp->tcph_seqnum = htonl(1 + 1);                        /* ADD SEQ NUM THINGY */
tcp->tcph_acknum = htonl (s_seq + 1);               /* ADD ACK NUM THINGY */
tcp->tcph_offset = 5;
tcp->tcph_flags = TH_ACK;
tcp->tcph_win = htons(32767);
tcp->tcph_chksum = 0; 
tcp->tcph_urgptr = 0;
tcp->tcph_chksum = (unsigned short) checksum_tcp((unsigned short) (ip->iph_len - ip->iph_ihl *4), (unsigned short *) &ip->iph_sourceip,
                    (unsigned short *) &ip->iph_destip,    (unsigned short *) &tcp);        


/* Address family */ 
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ip->iph_destip;

/* Send */
if (sendto(sock, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
    {
        fprintf(stderr, "\nCan't send packet\n");
        return (-1);
    }               
else
        printf("Packet sent to %d\n", dip); 

        close(sock);
}       

void run()
{
const int one = 1;
char buffer[PCKT_LEN];
struct sockaddr_in sin; 
struct ipheader *ip;
struct tcpheader *tcp;

ip = (struct ipheader *) buffer;
tcp = (struct tcpheader *) buffer + ip->iph_ihl *4;

sock = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
if (sock < 0)
    {
        fprintf(stderr, "\nSocket()\n\n");
        exit (-1);
    }
else
        printf ("socket() - Using SOCK_RAW and TCP protocol is OK.\n");

if ((setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&one, sizeof (one))) < 0)
    {
        fprintf(stderr, "Can't set socketoptions\n");
        exit (-1);
    }
else
        printf("Socketoptions OK.\n");  

send_syn(dip, sip, dport, sport);
}

void receive(u_char *args, const struct pcap_pkthdr *pkthdr, const u_char *buffer)
{
const int one = 1;
int LEN = strtol(args, NULL, 0);        /* LEN = strtol(args, NULL, 0)   ----  int LEN = *args;*/
struct ipheader *ip;
struct tcpheader *tcp;

ip = (struct ipheader *)(buffer + LEN);
tcp = (struct tcpheader *)(buffer + LEN + sizeof (struct ipheader));

printf("%d\n", LEN);

printf("Packet received. ACK number: %d\n", ntohl (tcp->tcph_seqnum));
printf("Packet received. SEQ number: %d\n", ntohl (tcp->tcph_acknum));
s_seq = ntohl (tcp->tcph_seqnum);

send_syn_ack(s_seq, dip, sip, dport, sport);    

sleep(100);
}

void capture()
{
pcap_t *pd;
bpf_u_int32 netmask;
bpf_u_int32 localnet;
char filterbuf[64];
snprintf(filterbuf, sizeof(filterbuf), "ip dst host %s", dstip); 
char *filter = filterbuf;       
char *dev = NULL;
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program filterprog;
int dl = 0, dl_len = 0;

if ((pd = pcap_open_live(dev, 1514, 1, 500, errbuf)) == NULL)       /* Look into snaplen size */
    {           
        fprintf(stderr, "can't open device %s: %s\n", dev, errbuf);
        exit(1);
    }

pcap_lookupnet(dev, &localnet, &netmask, errbuf);
pcap_compile(pd, &filterprog, filter, 0, localnet);
if (pcap_setfilter(pd, &filterprog) == - 1)
    {
        fprintf(stderr, "can't set pcap filter: %s %s\n", filter, errbuf);
        exit(1);
    }

pcap_freecode(&filterprog);
dl = pcap_datalink(pd);

switch(dl) {
    case 1:
        dl_len = 14;
        break;
    default:
        dl_len = 14;
        break;
}       

if (pcap_loop(pd, -1, receive, (u_char *) &dl_len) < 0) 
    {
        fprintf(stderr, "can't get raw packet: %s\n", pcap_geterr(pd));
        exit(1);
    }
}

void usage() 

{
/* This is the user manual (CHANGE) */  
printf("\nChannelBunny %s, created 2012\n\n", VERSION);

printf("ChannelBunny Usage:  -s -f <file> -i <destip> -p <destport> -o <sourceip> -t <sourceport>\n\n"); 

printf("-s, --send,             Puts program in send mode\n");
printf("-r, --receive,          Puts program in receive mode\n"); 
printf("-f, --file,             Specify file\n");       
printf("-i, --destip,           Destination IP address\n"); 
printf("-p, --destport,         Destination port\n"); 
printf("-o, --sourceip          Source IP address\n"); 
printf("-t, --sourceport        Source port\n");    
}
Was it helpful?

Solution

The main problem of your code is that you're not handling correctly the LINK-LAYER TYPE, you are using:

pcap_open_live with the fisrt argument set to NULL, this mean that the kernel will choose "any" interface to sniff and inject RAW packets, in this case your are using "LINKTYPE_LINUX_SLL" instead of ETHERNET which is what you want (LINK_TYPE 1).

So you need to handle the link layer correctly (checkout the list here: http://www.tcpdump.org/linktypes.html). I modify your code and it works now(replace device eth0 with what you want):

#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
#include <pcap.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define VERSION "1.0"
#define PCKT_LEN 8192

/* Prototypes */
int sock;
void run();
void* capture(void *);
void usage();
in_addr_t sip;
in_addr_t dip;
char *dstip = 0;
int s_seq;
unsigned short sport;
unsigned short dport;

struct pseudo {
    struct in_addr sourceip;
    struct in_addr destip;
    unsigned char placeholder;
    unsigned char protocol;
    unsigned char tcp_len;
    struct tcphdr tcp;
};

struct ipheader {

    unsigned char       iph_ihl:5,
        iph_ver:4;
    unsigned char       iph_tos;
    unsigned short int  iph_len;
    unsigned short int  iph_id;
    unsigned char       iph_flags;
    unsigned short int  iph_offset;
    unsigned char       iph_ttl;
    unsigned char       iph_protocol;
    unsigned short int  iph_chksum;
    unsigned int        iph_sourceip;
    unsigned int        iph_destip;
};

struct tcpheader {
    unsigned short int  tcph_sourceport;
    unsigned short int  tcph_destport;
    unsigned int        tcph_seqnum;
    unsigned int        tcph_acknum;
    unsigned char       tcph_reserved:4, tcph_offset:4;
    unsigned char       tcph_flags;
    unsigned short int  tcph_win;
    unsigned short int  tcph_chksum;
    unsigned short int  tcph_urgptr;
};



/* Checksum */
unsigned short checksum (unsigned short *pac, int len)
{
    unsigned long sum;
    for (sum = 0; len > 0; len--)
        sum += *pac++;
    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);

    return(~sum);
}

/* Checksum TCP */
unsigned short checksum_tcp (unsigned short len, unsigned short sourceip[],
    unsigned short destip[], unsigned short buf[])
{
    unsigned char protocol = 6;
    unsigned long sum;
    int nleft;
    unsigned short *w;

    sum = 0;
    nleft = len;
    w=buf;

    while(nleft > 1)
    {
        sum += *w++;
        nleft -= 2;
    }
    if(nleft > 0)
    {
        sum += *w&ntohs(0xFF00);
    }

    sum += sourceip[0];
    sum += sourceip[1];
    sum += destip[0];
    sum += destip[1];
    sum += htons(len);
    sum += htons(protocol);

    sum = (sum >> 16) + (sum & 0xFFFF);
    sum += (sum >> 16);
    sum = ~sum;

    return ((unsigned short) sum);
}

int main(int argc,char **argv)
{
    int c;

    /* Are we in root? */
    if(geteuid() !=0)
    {
        printf("Root access is required to run this program.\n\n");
        exit(0);
    }

    while (1)
    {
        static struct option long_options[] =
        {
        /* Options */
            {"send",       no_argument,       0, 's'}, /* args s, r and f have no function yet */
            {"receive",    no_argument,       0, 'r'},
            {"file",       required_argument, 0, 'f'},
            {"destip",     required_argument, 0, 'i'},
            {"destport",   required_argument, 0, 'p'},
            {"sourceip",   required_argument, 0, 'o'},
            {"sourceport", required_argument, 0, 't'},
            {0, 0, 0, 0}
        };

        int option_index = 0;
        c = getopt_long (argc, argv, "srf:d:i:p:o:t:",
        long_options, &option_index);

        /* Detect the end of the options. */
        if (c == -1)
            break;
        switch (c)
        {
            case 0: /* If this option set a flag, do nothing else now. */
            if (long_options[option_index].flag != 0)
                break;
            printf ("option %s", long_options[option_index].name);
            if (optarg)
                printf (" with arg %s", optarg);
            printf ("\n");
            break;

            case 's': puts ("option -s\n");
                break;
            case 'r': puts ("option -r\n");
                break;
            case 'f': printf ("option -f with value `%s'\n", optarg);
                break;
            case 'i': dip = inet_addr(optarg);
                dstip = optarg;
                break;
            case 'p': dport = htons(atoi(optarg));
                /* Add handling of bad/non number input here */
                break;
            case 'o': sip = inet_addr(optarg);
                break;
            case 't': sport = htons(atoi(optarg));
                break;
            case '?': /* Error message printed */
                break;
            default:  abort ();
        }
    }

    /* Print any remaining command line arguments (not options). */
    if (optind < argc)
    {
        printf ("\nNon-option ARGV-elements: ");
        while (optind < argc)
            printf ("%s ", argv[optind++]);
        putchar ('\n');
    }

    /* check if all mandatory options are set and for unknown arguments */
    /* This really needs changing... */
    if ((dip && sip && dport && sport) == 0)
    {
        usage();
        return (-1);
    }

    fprintf(stdout, "SPORT : %d, DPORT : %d\n", sport, dport);

    /* change */

    pthread_t tid_pr;
    if (pthread_create(&tid_pr, NULL, capture, NULL) != 0) {
        fprintf(stderr, "can't create raw packet reader: %s\n", strerror(errno));
        exit(1);
    }
    printf("\nRaw packet reader created\nWaiting 1 second for packet reader thread to settle down...\n\n");
    sleep(1);
    run();
    pthread_join(tid_pr, NULL);
    getchar ();

    exit (0);
}

int send_syn(unsigned int sourceip, unsigned int destip, unsigned short sourceport,
    unsigned short destport)
{
    //const int one = 1;
    char buffer[PCKT_LEN];
    struct sockaddr_in sin;
    struct ipheader *ip;
    struct tcpheader *tcp;

    ip = (struct ipheader *) buffer;
    tcp = (struct tcpheader *) buffer + ip->iph_ihl *4;

    /* IP attributes */
    ip->iph_ihl = 5;
    ip->iph_ver = 4;
    ip->iph_tos = 16;
    ip->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader);
    ip->iph_id = htons(54321);
    ip->iph_offset = 0;
    ip->iph_ttl = 64;
    ip->iph_protocol = IPPROTO_TCP;
    ip->iph_chksum = 0;
    ip->iph_sourceip = sip;
    ip->iph_destip = dip;
    ip->iph_chksum = checksum ((unsigned short *) buffer, (sizeof (struct
        ipheader )+ sizeof (struct tcpheader)));
    /* TCP attributes */
    tcp->tcph_sourceport = sport;
    tcp->tcph_destport = dport;
    tcp->tcph_seqnum = htonl(1);        /* ADD SEQ NUM THINGY */
    tcp->tcph_offset = 5;
    tcp->tcph_flags = TH_SYN;
    tcp->tcph_win = htons(32767);
    tcp->tcph_chksum = 0;
    tcp->tcph_urgptr = 0;
    tcp->tcph_chksum = (unsigned short) checksum_tcp((unsigned short) (ip->iph_len - ip->iph_ihl *4), (unsigned short *) &ip->iph_sourceip,
        (unsigned short *) &ip->iph_destip, (unsigned short *) &tcp);

    /* Address family */
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = ip->iph_destip;
    /* Send */
    if (sendto(sock, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
    {
        fprintf(stderr, "\nCan't send packet\n");
        return (-1);
    }
    else
        printf("Packet sent to %d", dip);
    close(sock);

    return 0;
}

int send_syn_ack(unsigned int sourceip, unsigned int destip, unsigned short sourceport,
    unsigned short destport, unsigned long s_seq)
{
    //const int one = 1;
    char buffer[PCKT_LEN];
    struct sockaddr_in sin;
    struct ipheader *ip;
    struct tcpheader *tcp;

    ip = (struct ipheader *) buffer;
    tcp = (struct tcpheader *) buffer + ip->iph_ihl *4;
    /* IP attributes */
    ip->iph_ihl = 5;
    ip->iph_ver = 4;
    ip->iph_tos = 16;
    ip->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader);
    ip->iph_id = htons(54321);
    ip->iph_offset = 0;
    ip->iph_ttl = 64;
    ip->iph_protocol = IPPROTO_TCP;
    ip->iph_chksum = 0;
    ip->iph_sourceip = sip;
    ip->iph_destip = dip;
    ip->iph_chksum = checksum ((unsigned short *) buffer, (sizeof (struct
        ipheader )+ sizeof (struct tcpheader)));
    /* TCP attributes */
    tcp->tcph_sourceport = sport;
    tcp->tcph_destport = dport;
    tcp->tcph_seqnum = htonl(1 + 1);                        /* ADD SEQ NUM THINGY */
    tcp->tcph_acknum = htonl (s_seq + 1);               /* ADD ACK NUM THINGY */
    tcp->tcph_offset = 5;
    tcp->tcph_flags = TH_ACK;
    tcp->tcph_win = htons(32767);
    tcp->tcph_chksum = 0;
    tcp->tcph_urgptr = 0;
    tcp->tcph_chksum = (unsigned short) checksum_tcp((unsigned short) (ip->iph_len - ip->iph_ihl *4), (unsigned short *) &ip->iph_sourceip,
        (unsigned short *) &ip->iph_destip,    (unsigned short *) &tcp);

    /* Address family */
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = ip->iph_destip;
    /* Send */
    if (sendto(sock, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
    {
        fprintf(stderr, "\nCan't send packet : %s\n", strerror(errno));
        return (-1);
    }
    else
        printf("Packet sent to %d\n", dip);
    close(sock);

    return 0;
}

void run()
{
    const int one = 1;
    //char buffer[PCKT_LEN];
    //struct sockaddr_in sin; 
    //struct ipheader *ip;
    //struct tcpheader *tcp;

    //ip = (struct ipheader *) buffer;
    //tcp = (struct tcpheader *) buffer + ip->iph_ihl *4;

    sock = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
    if (sock < 0)
    {
        fprintf(stderr, "\nSocket()\n\n");
        exit (-1);
    }
    else
        printf ("socket() - Using SOCK_RAW and TCP protocol is OK.\n");

    if ((setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&one, sizeof (one))) < 0)
    {
        fprintf(stderr, "Can't set socketoptions\n");
        exit (-1);
    }
    else
        printf("Socketoptions OK.\n");
    send_syn(dip, sip, dport, sport);
}

void receive(u_char *args, const struct pcap_pkthdr *pkthdr, const u_char *buffer)
{
    //const int one = 1;
    //int LEN = strtol(args, NULL, 0);        /* LEN = strtol(args, NULL, 0)   ----  int LEN = *args;*/
    int LEN = atoi((char *)args);
    //struct ipheader *ip;
    struct tcpheader *tcp;

    //ip = (struct ipheader *)(buffer + LEN);
    tcp = (struct tcpheader *)(buffer + LEN + sizeof (struct ipheader));

    printf("LEN = %d\n", LEN);

    printf("Packet received. ACK number: %d\n", ntohl (tcp->tcph_seqnum));
    printf("Packet received. SEQ number: %d\n", ntohl (tcp->tcph_acknum));
    s_seq = ntohl (tcp->tcph_seqnum);

    send_syn_ack(s_seq, dip, sip, dport, sport);

    sleep(100);
}

void* capture(void *unused_arg)
{
    pcap_t *pd;
    bpf_u_int32 netmask;
    bpf_u_int32 localnet;
    char filterbuf[64];
    snprintf(filterbuf, sizeof(filterbuf), "ip dst host %s", dstip);
    char *filter = filterbuf;
    //char *dev = NULL;
    char dev[] = "eth0";
    char errbuf[PCAP_ERRBUF_SIZE];
    struct bpf_program filterprog;
    int dl = 0, dl_len = 0;
    /* TODO : SET THE INTERFACE CORRECTLY */
    //if ((pd = pcap_open_live(dev, 1514, 1, 500, errbuf)) == NULL)       /* Look into snaplen size */
    if ((pd = pcap_open_live(dev, 1514, 1, 500, errbuf)) == NULL)       /* Look into snaplen size */
    {
        fprintf(stderr, "can't open device %s: %s\n", dev, errbuf);
        exit(1);
    }

    pcap_lookupnet(dev, &localnet, &netmask, errbuf);
    pcap_compile(pd, &filterprog, filter, 0, localnet);
    if (pcap_setfilter(pd, &filterprog) == - 1)
    {
        fprintf(stderr, "can't set pcap filter: %s %s\n", filter, errbuf);
        exit(1);
    }

    pcap_freecode(&filterprog);
    dl = pcap_datalink(pd);

    switch(dl) {
        /* TODO : HANDLE THIS PART CORRECTLY */
        case 1:
            dl_len = 14;    /* Ethernet header */
            fprintf(stdout, "\nDL = %d (ETHERNET)\n", dl);
            break;
        default:
            dl_len = 14;
            fprintf(stdout, "\nDL = %d (if you are here please handle correctly)\n", dl);
            break;
    }
    if (pcap_loop(pd, -1, receive, (u_char *) &dl_len) < 0)
    {
        fprintf(stderr, "can't get raw packet: %s\n", pcap_geterr(pd));
        exit(1);
    }

    return NULL;
}

void usage()

{
    /* This is the user manual (CHANGE) */
    printf("\nChannelBunny %s, created 2012\n\n", VERSION);
    printf("ChannelBunny Usage:  -s -f <file> -i <destip> -p <destport> -o <sourceip> -t <sourceport>\n\n");
    printf("-s, --send,             Puts program in send mode\n");
    printf("-r, --receive,          Puts program in receive mode\n");
    printf("-f, --file,             Specify file\n");
    printf("-i, --destip,           Destination IP address\n");
    printf("-p, --destport,         Destination port\n");
    printf("-o, --sourceip          Source IP address\n");
    printf("-t, --sourceport        Source port\n");
}

EDIT : Setting interface

To set the interface for pcap_open_live, use ifconfig command to check which interface you want to use, in the case of other interface than ETHERNET, you need to change your code, because the header will change.

To debug your code, you can use the old printf (it's always useful), add this in line in all parts that you suspect to be the cause of trouble:

fprintf(stdout, "Function : %s, Line : %d\n", __FUNCTION__, __LINE__);

EDIT2 : The value of the ETHERNET header passed to the receive function was wrong

Use :

int LEN = *(int *)args;

instead of:

int LEN = strtol(args, NULL, 0);

And then you can see clearly that the LEN is now 14 (Ethernet header length).

Another thing : i don't really understand how you think the global var sock will behave! your socket is created in the run function after the thread was launched! and you try to close it twice : inside send_syn_ack and send_syn. You need to think the design of your code (take some time to do so). I think that you should create the main socket inside the main function and close it when you want (inside the main function or when some errors occur). Last thing please use : strerror(errno) with all your calls so you can trace the errors easily. Hope this help.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top