Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C-IPv6原始ICMPv6数据包制作_C_Sockets_Ipv6_Icmp - Fatal编程技术网

C-IPv6原始ICMPv6数据包制作

C-IPv6原始ICMPv6数据包制作,c,sockets,ipv6,icmp,C,Sockets,Ipv6,Icmp,我目前正在尝试用C语言创建原始ICMPv6数据包。我只找到了工作正常的IPv4示例,我看不出IPv6有什么问题 到目前为止我所知道的: 我查阅了一份旧的表格,发现我需要在6_addr中设置一些变量(→ 错误22),但除此之外,他们正在使用: sock = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW); 另一方面,他们显然使用LIBNET。如果我能用插座的话,我宁愿避开图书馆。在这种情况下,如果不是通过socket.h,如何调用“networking API

我目前正在尝试用C语言创建原始ICMPv6数据包。我只找到了工作正常的IPv4示例,我看不出IPv6有什么问题

到目前为止我所知道的:

  • 我查阅了一份旧的表格,发现我需要在6_addr中设置一些变量(→ 错误22),但除此之外,他们正在使用:

    sock = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
    
  • 另一方面,他们显然使用LIBNET。如果我能用插座的话,我宁愿避开图书馆。在这种情况下,如果不是通过socket.h,如何调用“networking API”

  • 我读到,IP_HDRINCL在IPv6中没有等价物。(但为什么?)

下面的代码正在发送一个ICMPv6数据包,可能是由于IPPROTO_ICMPv6,但是添加了内核头和非常糟糕的数据包内容。。。(由于目的地地址错误,我还没有解决一些终端问题)。它在IPv6中工作。 当我使用IPPROTO_RAW时,数据包不会被发送

有什么想法吗?提前谢谢

#include <sys/types.h>
#include <sys/socket.h>

#include <netinet/in.h>
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
#include <arpa/inet.h>

#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

struct ipv6header {
    unsigned char priority:4, version:4;
    unsigned char flow[3];
    unsigned short int length;
    unsigned char nexthdr;
    unsigned char hoplimit;

    unsigned int saddr[4];
    unsigned int daddr[4];
};

struct icmpv6header {
    unsigned char type;
    unsigned char code;
    unsigned short int chk_sum;
    unsigned int body; 
};

int main()
{
    char* packet = (char*) malloc(sizeof(struct ipv6header)+sizeof(struct icmpv6header));
    struct ipv6header* ip = (struct ipv6header*) packet;
    struct icmpv6header* icmp = (struct icmpv6header*) (packet+sizeof(struct ipv6header));

    icmp->type = 128;
    icmp->code = 0;
    icmp->chk_sum = (0x6a13);
    icmp->body = htonl(1234);

    ip->version = 6;
    ip->priority = 0;
    (ip->flow)[0] = 0;
    (ip->flow)[1] = 0;
    (ip->flow)[2] = 0;
    ip->length = ((unsigned short int) sizeof(struct icmpv6header));
    ip->nexthdr = 58;
    ip->hoplimit = 255;

    struct sockaddr_in6 remote;
    remote.sin6_family = AF_INET6;
    remote.sin6_port = 0;
    remote.sin6_flowinfo = 0;
    remote.sin6_scope_id = 0;

    inet_pton(AF_INET6, "2001:470:x:x:y:y:y:dd7b", &(remote.sin6_addr));
    inet_pton(AF_INET6, "2001:470:x:x:bee:bee:bee:bee", &(ip->saddr));
    inet_pton(AF_INET6, "2001:470:x:x:y:y:y:dd7b", &(ip->daddr));

    int sock, optval;
    sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
    if(sock == -1)
    {
        printf("Error setting socket\n");
        return -1;
    }
    int ret = setsockopt(sock, IPPROTO_IPV6, IP_HDRINCL, &optval, sizeof(int));
    if(ret != 0) {
        printf("Error setting options %d\n", ret);
        return -1;
    }
    printf("Socket options done\n");

    int ret = sendto(sock, packet, ip->length, 0, (struct sockaddr *) &remote, sizeof(remote));

    if(ret != ip->length) {
        printf("Packet not sent : %d (%d)\n",ret,errno);
        return -1;
    }
    printf("Packet sent\n");

    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
结构ipv6header{
未签名字符优先级:4,版本:4;
无符号字符流[3];
无符号短整型长度;
未签名字符nexthdr;
无符号字符限制;
无符号整数saddr[4];
无符号int-daddr[4];
};
结构icmpv6header{
无符号字符类型;
无符号字符码;
无符号短整数chk_和;
无符号整数体;
};
int main()
{
char*packet=(char*)malloc(sizeof(struct ipv6header)+sizeof(struct icmpv6header));
结构ipv6header*ip=(结构ipv6header*)数据包;
结构icmpv6header*icmp=(结构icmpv6header*)(数据包+sizeof(结构ipv6header));
icmp->type=128;
icmp->code=0;
icmp->chk_和=(0x6a13);
icmp->body=htonl(1234);
ip->version=6;
ip->优先级=0;
(ip->流量)[0]=0;
(ip->流量)[1]=0;
(ip->流量)[2]=0;
ip->length=((无符号短整数)sizeof(结构icmpv6header));
ip->nexthdr=58;
ip->hoplimit=255;
远程6中的结构sockaddr_;
remote.sin6_family=AF_INET6;
remote.sin6_端口=0;
remote.sin6_flowinfo=0;
remote.sin6_scope_id=0;
inet_pton(AF_INET6,“2001:470:x:x:y:y:dd7b”和(remote.sin6_addr));
内特普顿(AF_INET6,“2001:470:x:x:bee:bee:bee:bee:bee”,&(ip->SADD));
网络电话(AF_INET6,“2001:470:x:x:y:y:dd7b”和(ip->daddr));
国际短袜,optval;
sock=插座(AF_INET6、sock_RAW、IPPROTO_ICMPV6);
如果(sock==-1)
{
printf(“错误设置套接字\n”);
返回-1;
}
int ret=setsockopt(sock、IPPROTO_IPV6、IP_HDRINCL和optval、sizeof(int));
如果(ret!=0){
printf(“错误设置选项%d\n”,ret);
返回-1;
}
printf(“套接字选项完成\n”);
int-ret=sendto(sock,packet,ip->length,0,(struct-sockaddr*)和remote,sizeof(remote));
如果(ret!=ip->长度){
printf(“数据包未发送:%d(%d)\n”,ret,errno);
返回-1;
}
printf(“已发送的数据包”);
返回0;
}

好的,经过几次代码重写后,我成功了: 主要问题是,当我使用
IPPROTO_RAW
时,由于数据包长度不正确,数据包被截断。结果,系统在它能够到达网络之前就丢弃了它。 我也变了

uint16_t daddr[8];

uint16_t ipdst[8]={htons(0x2001)、htons(0x470)、htons(x)、htons(x)、htons(y)、htons(y)、htons(y)、htons(0xdd7b)};
uint16_t ipsrc[8]={htons(0x2001)、htons(0x470)、htons(x)、htons(x)、htons(0xbee)、htons(0xbee)、htons(0xbee)、htons(0xbee)};
int j=0;
对于(j=0;jsaddr[j]=ipsrc[j];
ip->daddr[j]=ipdst[j];
}

谢谢!

在设置套接字选项时,我遇到了一个类似的问题,并通过使用
IPV6\u HDRINCL
而不是
IP\u HDRINCL
解决了它。

两个提示(但与您的问题无关):首先不要使用编译器定义的类型,如
char
short int
int
。使用
int8\u t
int16\u t
int32\u t
(或其无符号变体)从头文件。其次,。你在执行这个程序时是root吗?你能发布sudo strace程序的输出吗??感谢这些建议。我正在运行root。strace让我看到长度比预期的短!谢谢。还更正了类型和类型转换。
uint16_t ipdst[8] = {htons(0x2001),htons(0x470),htons(x),htons(x),htons(y),htons(y),htons(y),htons(0xdd7b)};
uint16_t ipsrc[8] = {htons(0x2001),htons(0x470),htons(x),htons(x),htons(0xbee),htons(0xbee),htons(0xbee),htons(0xbee)};

int j = 0;
for(j=0;j<=7;j++) {
    remote.sin6_addr.s6_addr16[j]=ipdst[j];
    ip->saddr[j]=ipsrc[j];
    ip->daddr[j]=ipdst[j];
}