2012-12-24 29 views
0

我一直试图在下面的代码。此代码我在互联网上找到的地方发送使用原始套接字的数据包。我创建了自己的ipheader和udp头文件。整个数据包使用原始套接字上的sendto()函数发送。 sendto()返回0.这意味着一个长度为0的数据包被发送出去,因此即使wireshark也没有检测到任何数据包。我的错误在哪里?Wireshark没有检测到任何发送的数据包。 SENDTO返回0

// Must be run by root lol! Just datagram, no payload/data 
#include <unistd.h> 
#include <stdio.h> 
#include <string.h> 
#include <cstdlib> 
#include <arpa/inet.h> 
#include <sys/socket.h> 
#include <netinet/ip.h> 
#include <netinet/udp.h> 

// The packet length 
#define PCKT_LEN 35 

// Can create separate header file (.h) for all headers' structure 
// The IP header's structure 
struct ipheader { 
    unsigned char  iph_ihl:4, iph_ver:4; 
    unsigned char  iph_tos; 
    unsigned short int iph_len; 
    unsigned short int iph_ident; 
    unsigned char  iph_flag; 
    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; 
}; 

// UDP header's structure 
struct udpheader { 
    unsigned short int udph_srcport; 
    unsigned short int udph_destport; 
    unsigned short int udph_len; 
    unsigned short int udph_chksum; 
}; 
// total udp header length: 8 bytes (=64 bits) 

// Function for checksum calculation. From the RFC, 
// the checksum algorithm is: 
// "The checksum field is the 16 bit one's complement of the one's 
// complement sum of all 16 bit words in the header. For purposes of 
// computing the checksum, the value of the checksum field is zero." 
unsigned short csum(unsigned short *buf, int nwords) 
{  // 
    unsigned long sum; 
    for(sum=0; nwords>0; nwords--) 
     sum += *buf++; 
    sum = (sum >> 16) + (sum &0xffff); 
    sum += (sum >> 16); 
    return (unsigned short)(~sum); 
} 

// Source IP, source port, target IP, target port from the command line arguments 
int main(int argc, char *argv[]) 
{ 
    int sd; 
    // No data/payload just datagram 
    char buffer[PCKT_LEN]; 
    // Our own headers' structures 
    struct ipheader *ip = (struct ipheader *) buffer; 
    struct udpheader *udp = (struct udpheader *) (buffer + sizeof(struct ipheader)); 
    // Source and destination addresses: IP and port 
    struct sockaddr_in sin, din; 
    int one = 1; 
    const int *val = &one; 

    memset(buffer, 0, PCKT_LEN); 

    if(argc != 5) 
    { 
     printf("- Invalid parameters!!!\n"); 
     printf("- Usage %s <source hostname/IP> <source port> <target hostname/IP> <target port>\n", argv[0]); 
     exit(-1); 
    } 

    // Create a raw socket with UDP protocol 
    sd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP); 
    if(sd < 0) 
    { 
     perror("socket() error"); 
     // If something wrong just exit 
     exit(-1); 
    } 
    else 
     printf("socket() - Using SOCK_RAW socket and UDP protocol is OK.\n"); 

    // The source is redundant, may be used later if needed 
    // The address family 
    sin.sin_family = AF_INET; 
    din.sin_family = AF_INET; 
    // Port numbers 
    sin.sin_port = htons(atoi(argv[2])); 
    din.sin_port = htons(atoi(argv[4])); 
    // IP addresses 
    sin.sin_addr.s_addr = inet_addr(argv[1]); 
    din.sin_addr.s_addr = inet_addr(argv[3]); 

    // Fabricate the IP header or we can use the 
    // standard header structures but assign our own values. 
    ip->iph_ihl = 5; 
    ip->iph_ver = 4; 
    ip->iph_tos = 16; // Low delay 
    ip->iph_len = sizeof(struct ipheader) + sizeof(struct udpheader); 
    ip->iph_ident = htons(54321); 
    ip->iph_ttl = 64; // hops 
    ip->iph_protocol = 17; // UDP 
    // Source IP address, can use spoofed address here!!! 
    ip->iph_sourceip = inet_addr(argv[1]); 
    // The destination IP address 
    ip->iph_destip = inet_addr(argv[3]); 

    // Fabricate the UDP header. Source port number, redundant 
    udp->udph_srcport = htons(atoi(argv[2])); 
    // Destination port number 
    udp->udph_destport = htons(atoi(argv[4])); 
    udp->udph_len = htons(sizeof(struct udpheader)); 
    // Calculate the checksum for integrity 
    ip->iph_chksum = csum((unsigned short *)buffer, sizeof(struct ipheader) + sizeof(struct udpheader)); 
    // Inform the kernel do not fill up the packet structure. we will build our own... 
    if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0) 
    { 
     perror("setsockopt() error"); 
     exit(-1); 
    } 
    else 
     printf("setsockopt() is OK.\n"); 

    // Send loop, send for every 2 second for 100 count 
    printf("Trying...\n"); 
    printf("Using raw socket and UDP protocol\n"); 
    printf("Using Source IP: %s port: %u, Target IP: %s port: %u.\n", argv[1], atoi(argv[2]), argv[3], atoi(argv[4])); 

    int count; 
    int i; 
    for(count = 1; count <=20; count++) 
    { 
     if(i = sendto(sd, buffer, PCKT_LEN, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0) 
     // Verify 
     { 
      perror("sendto() error"); 
      exit(-1); 
     } 
     else 
     { 
      printf("Count #%u - sendto() is OK. Data Length#%d\n", count,i); 
      sleep(2); 
     } 
    } 
    close(sd); 
    return 0; 
} 
+0

这太难以阅读。 – eve

+0

我编辑它使其“更好”,但我认为一些原始空间丢失了。也许Shashi可以编辑和使用{}来标记代码而不是''。 –

+0

然而,我认为0数据包len意味着“什么都没有发送”,所以wireshark不会看到任何东西,因为你从未发送过数据包。至于为什么,我不确定。 –

回答

3

阅读这段代码真的很难,也很难理解你在做什么,为什么。所以我可以推荐你看看我的代码片段:dhcp client implementation

查看函数getSock()以查看如何创建套接字以及如何在函数talker()上创建和发送完成的数据包。

+0

为什么减号?我已经给出了很好的例子(准备好使用代码)了解如何做到他想要的。 – fycth

+0

这有点苛刻,我同意 - 这是一个很好的答案。我给你一个upvote! –

+0

-1来自我。是的,你做过的一切,但它应该是一个*注释*,因为它并没有解决实际的问题(“哪里是我的错?”)。 @Mats Petersson:绝对不是*答案*。 –

6

啊哈!我至少有一部分。

i = sendto(sd, buffer, PCKT_LEN, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0 相同 i = (sendto(sd, buffer, PCKT_LEN, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)

你可能想: (i = sendto(sd, buffer, PCKT_LEN, 0, (struct sockaddr *)&sin, sizeof(sin))) < 0

你可能想:

  1. 打开你的编译器警告 - 至少如果你使用gcc ,这应该会给你一个警告,用于在相同的if语句中进行比较和分配。
  2. 用固定代码重试。

我确信你的代码中可能还有其他问题 - 我不是网络专家。

+0

Hey..ya ...对不起!但我仍不能看到wireshark..why那么什么吗? –

+1

我不知道。你确定你已经正确配置Wireshark的?例如。使用正确的接口,使用右协议等? –

0

本地IP报头结构是错误的...我的建议是,包括提供你的发行版的IP报头(您正在使用Linux呢?不是吗?)。

我没有什么只是包含linux/ip.h,重命名ipheader结构参照iphdr,并且根据在后者文件中描述的结构重命名IP报头字段。

我试图嗅出使用tcpdump包和现在的工作(我没有使用Wireshark尝试,但它必须工作太)

试试这个固定码:

// Must be run by root lol! Just datagram, no payload/data 
#include <unistd.h> 
#include <stdio.h> 
#include <string.h> 
#include <arpa/inet.h> 
#include <sys/socket.h> 
#include <netinet/udp.h> 
#include <linux/ip.h> 

// The packet length 
#define PCKT_LEN 35 

// UDP header's structure 
struct udpheader { 
    unsigned short int udph_srcport; 
    unsigned short int udph_destport; 
    unsigned short int udph_len; 
    unsigned short int udph_chksum; 
}; 
// total udp header length: 8 bytes (=64 bits) 

// Function for checksum calculation. From the RFC, 
// the checksum algorithm is: 
// "The checksum field is the 16 bit one's complement of the one's 
// complement sum of all 16 bit words in the header. For purposes of 
// computing the checksum, the value of the checksum field is zero." 
unsigned short csum(unsigned short *buf, int nwords) 
{  // 
    unsigned long sum; 
    for(sum=0; nwords>0; nwords--) 
     sum += *buf++; 
    sum = (sum >> 16) + (sum &0xffff); 
    sum += (sum >> 16); 
    return (unsigned short)(~sum); 
} 

// Source IP, source port, target IP, target port from the command line arguments 
int main(int argc, char *argv[]) 
{ 
    int sd; 
    // No data/payload just datagram 
    char buffer[PCKT_LEN]; 
    // Our own headers' structures 
    struct iphdr *ip = (struct iphdr *) buffer; 
    struct udpheader *udp = (struct udpheader *) (buffer + sizeof(struct iphdr)); 
    // Source and destination addresses: IP and port 
    struct sockaddr_in sin, din; 
    int one = 1; 
    const int *val = &one; 

    memset(buffer, 0, PCKT_LEN); 

    if(argc != 5) 
    { 
     printf("- Invalid parameters!!!\n"); 
     printf("- Usage %s <source hostname/IP> <source port> <target hostname/IP> <target port>\n", argv[0]); 
     exit(-1); 
    } 

    // Create a raw socket with UDP protocol 
    sd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP); 
    if(sd < 0) 
    { 
     perror("socket() error"); 
     // If something wrong just exit 
     exit(-1); 
    } 
    else 
     printf("socket() - Using SOCK_RAW socket and UDP protocol is OK.\n"); 

    // The source is redundant, may be used later if needed 
    // The address family 
    sin.sin_family = AF_INET; 
    din.sin_family = AF_INET; 
    // Port numbers 
    sin.sin_port = htons(atoi(argv[2])); 
    din.sin_port = htons(atoi(argv[4])); 
    // IP addresses 
    sin.sin_addr.s_addr = inet_addr(argv[1]); 
    din.sin_addr.s_addr = inet_addr(argv[3]); 

    // Fabricate the IP header or we can use the 
    // standard header structures but assign our own values. 
    ip->ihl = 5; 
    ip->version = 4; 
    ip->tos = 16; // Low delay 
    ip->tot_len = sizeof(struct iphdr) + sizeof(struct udpheader); 
    ip->id = htons(54321); 
    ip->ttl = 64; // hops 
    ip->protocol = 17; // UDP 
    // Source IP address, can use spoofed address here!!! 
    ip->saddr = inet_addr(argv[1]); 
    // The destination IP address 
    ip->daddr = inet_addr(argv[3]); 

    // Fabricate the UDP header. Source port number, redundant 
    udp->udph_srcport = htons(atoi(argv[2])); 
    // Destination port number 
    udp->udph_destport = htons(atoi(argv[4])); 
    udp->udph_len = htons(sizeof(struct udpheader)); 

    // Calculate the checksum for integrity 
    ip->check = csum((unsigned short *)buffer, sizeof(struct iphdr) + sizeof(struct udpheader)); 

    // Inform the kernel do not fill up the packet structure. we will build our own... 
    if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0) 
    { 
     perror("setsockopt() error"); 
     exit(-1); 
    } 
    else 
     printf("setsockopt() is OK.\n"); 

    // Send loop, send for every 2 second for 100 count 
    printf("Trying...\n"); 
    printf("Using raw socket and UDP protocol\n"); 
    printf("Using Source IP: %s port: %u, Target IP: %s port: %u.\n", argv[1], atoi(argv[2]), argv[3], atoi(argv[4])); 

    int count; 
    int i; 
    for(count = 1; count <=20; count++) 
    { 
     if((i = sendto(sd, buffer, PCKT_LEN, 0, (struct sockaddr *)&sin, sizeof(sin))) < 0) 
     // Verify 
     { 
      perror("sendto() error"); 
      exit(-1); 
     } 
     else 
     { 
      printf("Count #%u - sendto() is OK. Data Length# %d\n", count,i); 
      sleep(2); 
     } 
    } 
    close(sd); 
    return 0; 
} 
相关问题