2011-11-02 7 views
2

IPv6에서 작업 중이며 처음부터 IPv6 패킷을 만들어 버퍼에 넣어야합니다. 불행하게도, 난네이티브 C로 IPv6 원시 소켓 프로그래밍

struct ipheader { 
unsigned char  iph_ihl:5, /* Little-endian */ 
       iph_ver:4; 
unsigned char  iph_tos; 
unsigned short int iph_len; 
unsigned short int iph_ident; 
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; 
}; 

/* Structure of a TCP header */ 
struct tcpheader { 
unsigned short int tcph_srcport; 
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 int 
     tcp_res1:4,  /*little-endian*/ 
     tcph_hlen:4,  /*length of tcp header in 32-bit words*/ 
     tcph_fin:1,  /*Finish flag "fin"*/ 
     tcph_syn:1,  /*Synchronize sequence numbers to start a connection*/ 
     tcph_rst:1,  /*Reset flag */ 
     tcph_psh:1,  /*Push, sends data to the application*/ 
     tcph_ack:1,  /*acknowledge*/ 
     tcph_urg:1,  /*urgent pointer*/ 
     tcph_res2:2; 
unsigned short int tcph_win; 
unsigned short int tcph_chksum; 
unsigned short int tcph_urgptr; 
}; 

을 정의하여 내가 성공적으로의 IPv4와 같은 일을 한 튜토리얼에서 C.에 많은 경험을 가지고 같은 패킷의 내용을 기입하지 않습니다 IPv6에 대한 그러나

// IP structure 
    ip->iph_ihl = 5; 
    ip->iph_ver = 6; 
    ip->iph_tos = 16; 
    ip->iph_len = sizeof (struct ipheader) + sizeof (struct tcpheader); 
    ip->iph_ident = htons(54321); 
    ip->iph_offset = 0; 
    ip->iph_ttl = 64; 
    ip->iph_protocol = 6; // TCP 
    ip->iph_chksum = 0; // Done by kernel 

    // Source IP, modify as needed, spoofed, we accept through command line argument 
    ip->iph_sourceip = inet_addr("1922.168.1.128"); 
    // Destination IP, modify as needed, but here we accept through command line argument 
    ip->iph_destip = inet_addr(1922.168.1.1); 

    // The TCP structure. The source port, spoofed, we accept through the command line 
    tcp->tcph_srcport = htons(atoi("1024")); 
    // The destination port, we accept through command line 
    tcp->tcph_destport = htons(atoi("4201")); 
    tcp->tcph_seqnum = htons(1); 
    tcp->tcph_acknum = 0; 
    tcp->tcph_offset = 5; 
    tcp->tcph_syn = 1; 
    tcp->tcph_ack = 0; 
    tcp->tcph_win = htons(32767); 
    tcp->tcph_chksum = 0; // Done by kernel 
    tcp->tcph_urgptr = 0; 
    // IP checksum calculation 
    ip->iph_chksum = csum((unsigned short *) buffer, (sizeof (struct ipheader) + sizeof (struct tcpheader))); 

나는 비슷한 방법을 찾지 못했다. 내가 이미 발견 한 것은,

struct ip6_hdr { 

    union { 

     struct ip6_hdrctl { 
     uint32_t ip6_un1_flow; /* 4 bits version, 8 bits TC, 20 bits 
             flow-ID */ 
     uint16_t ip6_un1_plen; /* payload length */ 
     uint8_t ip6_un1_nxt; /* next header */ 
     uint8_t ip6_un1_hlim; /* hop limit */ 
     } ip6_un1; 

     uint8_t ip6_un2_vfc; /* 4 bits version, top 4 bits 
             tclass */ 
    } ip6_ctlun; 
    struct in6_addr ip6_src; /* source address */ 
    struct in6_addr ip6_dst; /* destination address */ 
}; 

IETF에서이 구조체이다하지만 예를 들어, 어떻게 2001에서 TCP/SYN를 보내, 정보를 입력하는 방법을 알고하지 않았다 : 220 : 806 : 22 : AACC : ff : fe00 : 1 포트 1024에서 2001 : 220 : 806 : 21 :: 4 포트 1025?

아무도 나를 도울 수 없습니까?

감사합니다.

이것은 내가 지금까지 해왔 던 것이지만, Wireshark에 의해 캡쳐 된 실제 패킷과 코드 사이에는 불일치가 있습니다 (아래의 코멘트에서 논의 됨). 코멘트 섹션에 긴 코드를 게시 할 수 있는지 확신 할 수 없기 때문에 질문을 편집합니다.

누구든지 도움을받을 수 있습니까?

#define PCKT_LEN 2000 

int main(void) { 
    unsigned char buffer[PCKT_LEN]; 
    int s; 
    struct sockaddr_in6 din; 
    struct ipv6_header *ip = (struct ipv6_header *) buffer; 
    struct tcpheader *tcp = (struct tcpheader *) (buffer + sizeof (struct ipv6_header)); 

    memset(buffer, 0, PCKT_LEN); 
    din.sin6_family = AF_INET6; 
    din.sin6_port = htons(0); 
    inet_pton(AF_INET6, "::1", &(din.sin6_addr)); // For routing 

    ip->version = 6; 
    ip->traffic_class = 0; 
    ip->flow_label = 0; 
    ip->length = 40; 
    ip->next_header = 6; 
    ip->hop_limit = 64; 
    inet_pton(AF_INET6, "::1", &(ip->dst)); // IPv6 
    inet_pton(AF_INET6, "::1", &(ip->src)); // IPv6 

    tcp->tcph_srcport = htons(atoi("11111")); 
    tcp->tcph_destport = htons(atoi("13")); 
    tcp->tcph_seqnum = htons(0); 
    tcp->tcph_acknum = 0; 
    tcp->tcph_offset = 5; 
    tcp->tcph_syn = 1; 
    tcp->tcph_ack = 0; 
    tcp->tcph_win = htons(32752); 
    tcp->tcph_chksum = 0; // Done by kernel 
    tcp->tcph_urgptr = 0; 

    s = socket(PF_INET6, SOCK_RAW, IPPROTO_RAW); 
    if (s < 0) { 
     perror("socket()"); 
     return 1; 
    } 
    unsigned short int packet_len = sizeof (struct ipv6_header) + sizeof (struct tcpheader); 
    if (sendto(s, buffer, packet_len, 0, (struct sockaddr*) &din, sizeof (din)) == -1) { 
     perror("sendto()"); 
     close(s); 
     return 1; 
    } 
    close(s); 
    return 0; 
} 

답변

1

this 문서가 도움이 되십니까?

편집 :

struct ipv6_header 
{ 
    unsigned int 
     version : 4, 
     traffic_class : 8, 
     flow_label : 20; 
    uint16_t length; 
    uint8_t next_header; 
    uint8_t hop_limit; 
    struct in6_addr src; 
    struct in6_addr dst; 
}; 

그것은 헤더 - 구조체는 IPv4를 위해 만들어진 방법 다르지 없습니다 : I 위에 링크 된 위키 피 디아 문서를 사용 는 (일부 필드의 의미를 모른 채)이 구조를 만들어 당신의보기에서. 올바른 순서와 올바른 크기로 입력란을 포함하는 struct을 만들고 올바른 값으로 입력하십시오.

TCP 헤더에 대해서도 똑같이하십시오.

+0

예 IPv6가 무엇인지는 잘 알고 있지만 C 언어로 구현하는 방법은 익숙하지 않기 때문에 나에게 어렵습니다. 예를 들어, IPv4 구조체는 매우 간단하며 정보를 쉽게 이해하고 채울 수 있습니다. 그러나 IPv6의 경우에는 상당히 다릅니다. – nhong

+0

@nhong : 답변이 약간 업데이트되었습니다. –

+0

답장을 보내 주셔서 감사합니다. 이것은 IETF에서 가져온 구조체와는 다소 차이가 있지만 어쨌든, 시도해 보겠습니다. :) – nhong

0

불행히도 ipv6 RFC는 ipv4와 동일한 원시 소켓 인터페이스를 제공하지 않습니다. 내가 ipv6 패킷을 생성하는 것으로부터 좀 더 깊이 가서 AF_PACKET 소켓을 사용하여 ipv6 패킷을 포함한 이더넷 프레임을 보내야합니다.