2011-08-09 9 views
1

cでパケットを生成する方法を知りたい。パケットを生成する

struct ipheader { 
    int version; 
    int hdLen; 
    int tos; 
    int totLen; 
    int id; 
    ...... 
    int dstIp; 
} 

を我々はIPヘッダのタイプがあります:私は「IP」から(単にIPヘッダ部分)パケットを生成することができますどのように

struct ipheader ip; 

//init the ip 
..... 

を次のように私たちはタイプを持っているはず。誰も私にどのように表示することができますか?

私は、MACアドレス、IPヘッダ、TCPヘッダ、ペイロードなどの情報を含むパケットを生成することを知りたいと思っています。それから私は "pcap_sendpacket"関数を使って私が生成したパケットを送ることができます。誰かが私に少しの例を与えることができます。

+1

"パケットを生成しますか?"この文脈では、それはどういう意味ですか? – cdhowie

+0

あなたはフィールドの長さを正しく指定していません... –

答えて

2

以下のようにカスタムIPパケットを作成することができます。以下のコードスニペットは、ipパケットの中にあるカスタムTCP部分も作成します。また、カスタム関数チェックサムはパケットのチェックサムを生成します。 rawsocketを使ってこのパケットをネットワークに直接送ることができます。私はコードが簡単で自明だと思う。あなたが何か質問がある場合は私に教えてください。

#include <netinet/ip.h> 
#include <netinet/tcp.h> 


**************************************** 
ipv4 packet structure 
**************************************** 
struct ipv4_packet { 
    struct iphdr iph; 
    struct tcphdr tcph; 
    void *data; 
}; 


**************************************** 
snippet of the IPV4 packet making code 
**************************************** 
struct iphdr ip_head; 
struct tcphdr tcp_head; 
struct sockaddr_in target; 
char packet[2048]; 
int i; 

struct tcp_pseudo /*the tcp pseudo header*/ 
{ 
    __u32 src_addr; 
    __u32 dst_addr; 
    __u8 dummy; 
    __u8 proto; 
    __u16 length; 
} pseudohead; 

struct help_checksum /*struct for checksum calculation*/ 
{ 
    struct tcp_pseudo pshd; 
    struct tcphdr tcphd; 
    char tcpdata[1024]; 
} tcp_chk_construct; 

/*Prepare IP header*/ 
ip_head.ihl = 5; /*headerlength with no options*/ 
ip_head.version = 4; 
ip_head.tos = 0; 
ip_head.tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr) + len); 
ip_head.id = htons(31337 + (rand() % 100)); 
ip_head.frag_off = 0; 
ip_head.ttl = 255; 
ip_head.protocol = IPPROTO_TCP; 
ip_head.check = 0; /*Fill in later*/ 
ip_head.saddr = htonl(src); 
ip_head.daddr = htonl(dst); 
ip_head.check = in_cksum((unsigned short *) &ip_head, sizeof(struct iphdr)); 

/*Prepare TCP header*/ 
tcp_head.source = htons(src_p); 
tcp_head.dest = htons(dst_p); 
tcp_head.seq = htonl(seq); 
tcp_head.ack_seq = htonl(ack); 
tcp_head.doff = 5; 

/* set or reset ack, fin or syn flags as needed */ 
tcp_head.ack = 0; 
tcp_head.syn = 0; 
tcp_head.fin = 0; 

tcp_head.res1 = 0; 
tcp_head.urg = 0; 
tcp_head.psh = 0; 
tcp_head.rst = 0; 
tcp_head.res2 = 0; 

tcp_head.window = htons(0x7c00); 
tcp_head.check = 0; /*Fill in later*/ 
tcp_head.urg_ptr = 0; 

/*Assemble structure for checksum calculation and calculate checksum*/ 
pseudohead.src_addr = ip_head.saddr; 
pseudohead.dst_addr = ip_head.daddr; 
pseudohead.dummy = 0; 
pseudohead.proto = ip_head.protocol; 
pseudohead.length = htons(sizeof(struct tcphdr) + len); 

tcp_chk_construct.pshd = pseudohead; 
tcp_chk_construct.tcphd = tcp_head; 
memcpy(tcp_chk_construct.tcpdata, buffer, len); 

tcp_head.check = in_cksum((unsigned short *) &tcp_chk_construct, 
     sizeof(struct tcp_pseudo) + sizeof(struct tcphdr) + len); 

/*Assemble packet*/ 
memcpy(packet, (char *) &ip_head, sizeof(ip_head)); 
memcpy(packet + sizeof(ip_head), (char *) &tcp_head, sizeof(tcp_head)); 
memcpy(packet + sizeof(ip_head) + sizeof(tcp_head), buffer, len); 

/*Send packet*/ 
target.sin_family = AF_INET; 
target.sin_addr.s_addr = ip_head.daddr; 
target.sin_port = tcp_head.dest; 
i = sendto(sfd, packet, sizeof(struct iphdr) + sizeof(struct tcphdr) + len, 
     0, (struct sockaddr *) &target, sizeof(struct sockaddr_in)); 
if (i < 0) 
    return (-1); /*Error*/ 
else 
    return (i); /*Return number of bytes sent*/ 


****************************************   
FUNCTION FOR CHECKSUM 
**************************************** 
/* function to calculate the checksum for the packet */ 
unsigned short in_cksum(unsigned short *ptr, int nbytes) { 

    register long sum; /* assumes long == 32 bits */ 
    u_short oddbyte; 
    register u_short answer; /* assumes u_short == 16 bits */ 
    /* 
    * the algorithm is simple, using a 32-bit accumulator (sum), 
    * we add sequential 16-bit words to it, and at the end, fold back 
    * all the carry bits from the top 16 bits into the lower 16 bits. 
    */ 
    sum = 0; 
    while (nbytes > 1) { 
     sum += *ptr++; 
     nbytes -= 2; 
    } 

    /* mop up an odd byte, if necessary */ 
    if (nbytes == 1) { 
     oddbyte = 0; /* make sure top half is zero */ 
     *((u_char *) &oddbyte) = *(u_char *) ptr; /* one byte only */ 
     sum += oddbyte; 
    } 

    /* 
    * Add back carry outs from top 16 bits to low 16 bits. 
    */ 
    sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */ 
    sum += (sum >> 16); /* add carry */ 
    answer = ~sum; /* ones-complement, then truncate to 16 bits */ 
    return (answer); 
} 
0

あなたは細部を指定していないので(私には宿題のように疑わしいように見えます)、私はポインタを与えるだけです。

  1. 構造体がメモリにどのように形成されているかを調べます。
  2. IPヘッダーのどのメンバーがどこにあるかを示すIPヘッダー形式を調べます。
  3. Rawソケットをルックアップします。

構造体を適切に構造化して未処理のソケットを使用する場合は、この構造体をソケットに書き込むだけで済みます。

関連する問題