Note that there are some explanatory texts on larger screens.

plurals
  1. PODont fragment flag for IPv6 packets in Linux using C++
    primarykey
    data
    text
    <p>I can not set the "don't fragment" flag for the IPv6/ICMPv6 packets. I am doing PMTUD and I want to force the router to drop packets bigger then the MTU. Using setsockopt with IPV6_MTU_DISCOVER is not working.</p> <pre><code>int on = IPV6_PMTUDISC_DO; // tried also IPV6_PMTUDISC_PROBE setsockopt(socket, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &amp;on, sizeof(on)); </code></pre> <p>result: <img src="https://i.stack.imgur.com/SBLxw.png" alt="wireshark"></p> <p>I also can not use setosckopt with <code>IPV6_DONTFRAG</code> as described in <em>Unix-Linux Addison-Wesley - Stevens2003 - Unix Network Programming</em> because I have the <code>netinet/in6.h</code> header included and <code>IPV6_DONTFRAG</code> is defined in <code>linux/in6.h</code>. Including <code>linux/in6.h</code> in my source code causes these redefinition errors. </p> <pre><code>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 </code></pre> <p>Environment: Ubuntu 12.10 on VirtualBox 4.26 and GNS3 for the virtual network. The virtual Cisco C3660 router has just basic configuration: ip, ipv6 address, no shut and set mtu.</p> <p><strong>EDIT:</strong> I need the IPv6 stack/OS kernel to drop packets that are bigger than the link MTU or to signalize "this packet needs fragmentation". How can I achieve this behavior? </p> <p>I tried <code>setsockopt</code> with <code>IPV6_DONTFRAG</code> (defined it in my code <code>#define IPV6_DONTFRAG 62</code> ), <code>setsockopt</code> with <code>IPV6_MTU_DISCOVER</code>, <code>int on = IPV6_PMTUDISC_DO</code> and <code>setsockopt</code> with <code>IPV6_RECVPATHMTU</code>.</p> <p>But I am not getting the <code>PACKET TOO BIG</code> reply or <code>ancillary data</code> with <code>cmsg_level == IPPROTO_IPV6</code> and <code>cmsg_type == IPV6_PATHMTU.</code></p> <p>Part of my code:</p> <pre><code>/** sending ICMP packet*/ if (((length = sendto(mysocket, packet, lengthBuff, 0, result-&gt;ai_addr, result-&gt;ai_addrlen)) &lt; 0) &amp;&amp; (errno == EMSGSIZE)){ // works for IPv4, doesn't work with IPv6 cout &lt;&lt; "changing maxBuff and lengthBuff size" &lt;&lt; endl; maxBuff = lengthBuff; lengthBuff = (minBuff + maxBuff) / 2; if (packet) { delete(packet); packet = NULL; } } else if (length &lt; 0){ cerr &lt;&lt; "Error: sending data." &lt;&lt; endl; freeaddrinfo(result); close(mysocket); if (packet) { delete(packet); packet = NULL; } exit(1); } else if(((recvmsg(mysocket, &amp;msg, 0)) != -1) &amp;&amp; (errno != EINTR)) { // reading ancillary dada as described in *Unix-Linux Addison-Wesley - Stevens2003 - Unix Network Programming, page 736* cmsgh = CMSG_FIRSTHDR(&amp;msg); if(cmsgh != NULL) { cout &lt;&lt; "getting msg " &lt;&lt; endl; cout &lt;&lt; "msg len " &lt;&lt; msg.msg_controllen &lt;&lt; endl; if(cmsgh-&gt;cmsg_level == IPPROTO_ICMPV6 &amp;&amp; cmsgh-&gt;cmsg_type == IPV6_PATHMTU) { cout &lt;&lt; "CMSGHEADER - GOOD" &lt;&lt; endl; //mtustruct = CMSG_DATA(&amp;msg); maxBuff = lengthBuff; lengthBuff = (minBuff + maxBuff) / 2; if (packet) { delete(packet); packet = NULL; } } else{ cout &lt;&lt; "different ancillary data. " &lt;&lt; endl; cout &lt;&lt; " level " &lt;&lt; cmsgh-&gt;cmsg_level &lt;&lt; " type " &lt;&lt; cmsgh-&gt;cmsg_type &lt;&lt; endl; } } } else { cout &lt;&lt; "no ERROR with sendto and no RESCVMSG" &lt;&lt; endl; } /** receiving ICMP data */ tv.tv_sec = 3; tv.tv_usec = 0; int retval; // select FD_ZERO(&amp;mySet); FD_SET(mysocket, &amp;mySet); retval = select(mysocket + 1, &amp;mySet, NULL, NULL, &amp;tv); if (retval == -1) { cerr &lt;&lt; "select failed" &lt;&lt; endl; //break; exit(1); } else if (retval) { if ((length = recvfrom(mysocket, buffer, MAX, 0, result-&gt;ai_addr, &amp;(result-&gt;ai_addrlen))) == -1) { cerr &lt;&lt; "Error: receiving data." &lt;&lt; endl; } else { icmpRec = (struct icmp6_hdr*) buffer; if((icmpRec-&gt;icmp6_type == ICMP6_PACKET_TOO_BIG)) { cout &lt;&lt; "next hop MTU: " &lt;&lt; ntohl(icmpRec-&gt;icmp6_mtu) &lt;&lt; endl; maxBuff = ntohl(icmpRec-&gt;icmp6_mtu); } else if ((icmpRec-&gt;icmp6_type == ICMP6_ECHO_REPLY) &amp;&amp; (ntohs(icmpRec-&gt;icmp6_id) == pid) &amp;&amp; (ntohs(icmpRec-&gt;icmp6_seq) == (seq - 1))) { cout &lt;&lt; "code " &lt;&lt; ntohs(icmpRec-&gt;icmp6_code) &lt;&lt; endl; cout &lt;&lt; "ICMP ECHO REPLY" &lt;&lt; endl; minBuff = lengthBuff; } } } </code></pre> <p><strong>EDIT2:</strong> I realized, <code>setsockopt</code> with defined <code>IPV6_DONTFRAG</code> is not working for me, but <code>setsockopt</code> with <code>IPV6_MTU_DISCOVER</code> is working for the own interface. The eth1 interface MTU is 1500 (default) and if <code>sendto</code> wants to send packets with bigger size, <code>errno</code> is set to <code>EMSGSIZE</code>. Also after some time I get <code>PACKET TOO BIG</code> message for these not send messages fom the <strong>own kernel/OS</strong>. </p> <p>My real problem is, I am <strong>not</strong> getting (Ubuntu 12.10 running on VirtualBox 4.2.6) <code>PACKET TOO BIG</code> messages from the virtual router (Cisco c3660) running on GNS3.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload