C - 程序冻结; futex_wait_queue_me

时间:2012-08-21 20:11:08

标签: c sockets network-programming freeze futex

我已按要求将完整的代码包含在内,以便您可以对其进行测试。请记住,这远未完成,但应该能够通过稳定的TCP连接发送和接收数据包。

当我跑步时,我得到:

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

然后它就会挂起。我也使用了strace,这给了我(只包括它停止的最后一位):

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

并且系统监视器说程序正在休眠,并给出futex_wait_queue_me。

这可能会导致内存泄漏导致对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");    
}

1 个答案:

答案 0 :(得分:2)

您的代码的主要问题是您没有正确处理正在使用的 LINK-LAYER TYPE

将fisrt参数设置为pcap_open_live

NULL,这意味着内核将选择“any”接口来嗅探并注入RAW数据包,在这种情况下你的是使用“LINKTYPE_LINUX_SLL”代替您想要的ETHERNET(LINK_TYPE 1)。

所以你需要正确处理链接层(在这里查看列表:http://www.tcpdump.org/linktypes.html)。我修改了你的代码,它现在可以正常工作(用您想要的设备替换设备eth0):

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

编辑:设置界面

要设置pcap_open_live的接口,请使用ifconfig命令检查要使用的接口,如果是其他接口而不是ETHERNET,则需要更改代码,因为标题将改变。

要调试你的代码,你可以使用旧的printf(它总是很有用),在你怀疑引起麻烦的所有部分中加入这个:

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

EDIT2 :传递给receive函数的ETHERNET标头的值错误

使用:

int LEN = *(int *)args;

而不是:

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

然后您可以清楚地看到LEN现在是14(以太网标头长度)。

另一件事:我真的不明白你认为全局var sock会如何表现!线程启动后,您的套接字在run函数中创建!并尝试关闭它两次:在send_syn_acksend_syn内。 您需要考虑代码的设计(花一些时间来完成)。 我认为您应该在main函数中创建主套接字并在需要时关闭它(在main函数内部或发生一些错误时)。 最后一件事请使用:strerror(errno)和你的所有电话,这样你就可以轻松追踪错误。 希望这有帮助。