linux c ip数据包,不要使用C在Linux中分割IPv6数据包的标志

我无法为IPv6 / ICMPv6数据包设置“do not fragment”标志.我正在做PMTUD,我想强制路由器丢弃比MTU更大的数据包.使用setsockopt和IPV6_MTU_DISCOVER不起作用.

int on = IPV6_PMTUDISC_DO; // tried also IPV6_PMTUDISC_PROBE

setsockopt(socket, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &on, sizeof(on));

结果:

我也不能像在Unix-Linux Addison-Wesley-Stevens2003-Unix网络编程中所描述的那样使用带有IPV6_DONTFRAG的setosckopt,因为我包含了netinet / in6.h头文件,并且在linux / in6.h中定义了IPV6_DONTFRAG.在我的源代码中包含linux / in6.h会导致这些重定义错误.

In file included from mypmtud.cc:30:0: /usr/include/linux/in6.h:30:8: error: redefinition of ‘struct in6_addr’ In file included from /usr/include/netdb.h:28:0,

from mypmtud.cc:23: /usr/include/netinet/in.h:198:8: error: previous definition of ‘struct in6_addr’ In file included from mypmtud.cc:30:0: /usr/include/linux/in6.h:46:8: error: redefinition of ‘struct sockaddr_in6’ In file included from /usr/include/netdb.h:28:0,

from mypmtud.cc:23: /usr/include/netinet/in.h:239:8: error: previous definition of ‘struct sockaddr_in6’ In file included from mypmtud.cc:30:0: /usr/include/linux/in6.h:54:8: error: redefinition of ‘struct ipv6_mreq’ In file included from /usr/include/netdb.h:28:0,

from mypmtud.cc:23: /usr/include/netinet/in.h:275:8: error: previous definition of ‘struct ipv6_mreq’ make: *** [mypmtud] Error 1

环境:VirtualBox 4.26上的Ubuntu 12.10和虚拟网络的GNS3.虚拟Cisco C3660路由器只有基本配置:ip,ipv6地址,无关闭和设置mtu.

编辑:

我需要IPv6堆栈/操作系统内核丢弃大于链路MTU的数据包或发出“此数据包需要分段”的信号.我怎样才能实现这种行为?

我尝试了使用IPV6_DONTFRAG的setsockopt(在我的代码#define IPV6_DONTFRAG 62中定义),setsockopt与IPV6_MTU_DISCOVER,int on = IPV6_PMTUDISC_DO和setsockopt与IPV6_RECVPATHMTU.

但我没有得到包含大量回复或辅助数据与cmsg_level == IPPROTO_IPV6和cmsg_type == IPV6_PATHMTU.

我的部分代码:

/** sending ICMP packet*/

if (((length = sendto(mysocket, packet, lengthBuff, 0, result->ai_addr, result->ai_addrlen)) < 0) && (errno == EMSGSIZE)){

// works for IPv4, doesn't work with IPv6

cout << "changing maxBuff and lengthBuff size" << endl;

maxBuff = lengthBuff;

lengthBuff = (minBuff + maxBuff) / 2;

if (packet) {

delete(packet);

packet = NULL;

}

} else if (length < 0){

cerr << "Error: sending data." << endl;

freeaddrinfo(result);

close(mysocket);

if (packet) {

delete(packet);

packet = NULL;

}

exit(1);

} else if(((recvmsg(mysocket, &msg, 0)) != -1) && (errno != EINTR)) {

// reading ancillary dada as described in *Unix-Linux Addison-Wesley - Stevens2003 - Unix Network Programming, page 736*

cmsgh = CMSG_FIRSTHDR(&msg);

if(cmsgh != NULL) {

cout << "getting msg " << endl;

cout << "msg len " << msg.msg_controllen << endl;

if(cmsgh->cmsg_level == IPPROTO_ICMPV6 && cmsgh->cmsg_type == IPV6_PATHMTU)

{

cout << "CMSGHEADER - GOOD" << endl;

//mtustruct = CMSG_DATA(&msg);

maxBuff = lengthBuff;

lengthBuff = (minBuff + maxBuff) / 2;

if (packet) {

delete(packet);

packet = NULL;

}

}

else{

cout << "different ancillary data. " << endl;

cout << " level " << cmsgh->cmsg_level << " type " << cmsgh->cmsg_type << endl;

}

}

} else {

cout << "no ERROR with sendto and no RESCVMSG" << endl;

}

/** receiving ICMP data */

tv.tv_sec = 3;

tv.tv_usec = 0;

int retval; // select

FD_ZERO(&mySet);

FD_SET(mysocket, &mySet);

retval = select(mysocket + 1, &mySet, NULL, NULL, &tv);

if (retval == -1) {

cerr << "select failed" << endl;

//break;

exit(1);

} else if (retval) {

if ((length = recvfrom(mysocket, buffer, MAX, 0, result->ai_addr, &(result->ai_addrlen))) == -1) {

cerr << "Error: receiving data." << endl;

} else {

icmpRec = (struct icmp6_hdr*) buffer;

if((icmpRec->icmp6_type == ICMP6_PACKET_TOO_BIG)) {

cout << "next hop MTU: " << ntohl(icmpRec->icmp6_mtu) << endl;

maxBuff = ntohl(icmpRec->icmp6_mtu);

} else if ((icmpRec->icmp6_type == ICMP6_ECHO_REPLY) && (ntohs(icmpRec->icmp6_id) == pid) && (ntohs(icmpRec->icmp6_seq) == (seq - 1))) {

cout << "code " << ntohs(icmpRec->icmp6_code) << endl;

cout << "ICMP ECHO REPLY" << endl;

minBuff = lengthBuff;

}

}

}

EDIT2:

我意识到,使用已定义的IPV6_DONTFRAG的setsockopt对我来说不起作用,但是带有IPV6_MTU_DISCOVER的setsockopt正在为自己的接口工作. eth1接口MTU为1500(默认),如果sendto想要发送更大的数据包,则errno设置为EMSGSIZE.也有一段时间后,我得到PACKET TOO BIG消息,因为这些消息不是从自己的内核/操作系统发送消息.

我真正的问题是,我没有得到(Ubuntu 12.10在VirtualBox 4.2.6上运行)来自在GNS3上运行的虚拟路由器(Cisco c3660)的PACKET TOO BIG消息.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值