LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   C - Program freezes; futex_wait_queue_me (http://www.linuxquestions.org/questions/programming-9/c-program-freezes%3B-futex_wait_queue_me-4175423410/)

megustalinux 08-22-2012 07:58 AM

C - Program freezes; futex_wait_queue_me
 
I am having problems with my program going in futex_wait_queue_me mode.

I have included the code in its entirety so that you can test it if you want. 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:

Code:

./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):

Code:

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.

Code:

    #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");       
    }


H_TeXMeX_H 08-22-2012 09:36 AM

I'm no expert but maybe this is not right:

Code:

int send_syn(unsigned int sourceip, unsigned int destip, unsigned short sourceport,
                                unsigned short destport)
...
send_syn(dip, sip, dport, sport);

maybe it should be:

Code:

send_syn(sip, dip, sport, dport);
I haven't checked the entire code.

megustalinux 08-22-2012 10:36 AM

Thanks for the effort TexMex but I'm afraid that had no effect. The frustrating bit is that there's almost no help in googling either.. just can't find anything useful (or rather that I can make use of).

sundialsvcs 08-23-2012 08:45 AM

Add more, more, more diagnostic print messages until you can zero-in on exactly where the messages stop. Make the debugging messages positively chatty.

H_TeXMeX_H 08-23-2012 08:57 AM

Try using gdb as well. Load the file and see where it hangs.


All times are GMT -5. The time now is 07:39 PM.