title: How to send modified IPv6 packet through RAW socket?
body: <p>I'm trying to send a custom IPv6 header through a RAW socket in C Linux.<br>
  I already succeded in IPv4 using the IP_HDRINCL socket option, however, there's not an equivalent for IPv6.
  <br>
  I found a workaround <a href="http://lists.openwall.net/netdev/2009/01/15/168" rel="noreferrer">here</a> suggesting to use <code>socket(AF_INET6, SOCK_RAW, IPPROTO_RAW)</code> to have the same effect as enabling the IP_HDRINCL socket option.<br>
  <br>
  The socket is created successfully and I'm not getting any error until I use the <code>sendto</code> function with my modified header.</p>
  
  <p>I setup the socket like this:</p>
  
  <pre><code>static int socketFd = 0;
  static struct sockaddr_in6 remote;
  
  int main()
  {
      socketFd = socket (PF_INET6, SOCK_RAW, IPPROTO_RAW);
  
      if (socketFd &lt; 0)
      {
          printf ("An error ocurred while creating the socket.\n");
          exit (2);
      }
  
      remote.sin6_family = AF_INET6;
      remote.sin6_port = htons (25000);
  
      if (inet_pton (AF_INET6, "fd00:c0de::70d6:4ab9:115d:8cda", &amp;(remote.sin6_addr)) != 1)
      {
          close (socketFd);
          printf ("Unable to parse IPv6 address.\n");
          exit (2);
      }
  
   /*More code */
    ...
  
    return 0;
  }
  </code></pre>
  
  <p>And then, I have this callback function that should send my custom IPv6 packets but <code>sendto</code> fails returning EINVAL.</p>
  
  <pre><code>static void sendPacket ()
  {
      char buffer[BUFSIZ];
      const size_t len = sizeof(struct ip6_hdr) + sizeof(struct UDP_hdr);
      struct ip6_hdr *ip6 = (struct ip6_hdr*) (buffer);
      struct UDP_hdr *udp = (struct UDP_hdr *) (buffer + sizeof(struct ip6_hdr));
  
      memset (buffer, 0, BUFSIZ);
  
      ip6-&gt;ip6_ctlun.ip6_un2_vfc = 0x60;
      ip6-&gt;ip6_dst = remote.sin6_addr;
      ip6-&gt;ip6_flow = 60;
      ip6-&gt;ip6_hops = 64;
      ip6-&gt;ip6_nxt = 17;
      ip6-&gt;ip6_plen = sizeof(struct UDP_hdr);
  
      if (inet_pton (AF_INET6, "fd00:c0de::62a4:4cff:1234:5678", &amp;(ip6-&gt;ip6_src)) != 1)
      {
          printf ("Error while parsing spoofed IPv6 address.\n");
          return;
      }
  
      // Fabricate the UDP header. Source port number, redundant
      udp-&gt;uh_sport = htons (21000);
      // Destination port number
      udp-&gt;uh_dport = remote.sin6_port;
      udp-&gt;uh_ulen = htons (sizeof(struct UDP_hdr));
  
      if (sendto (socketFd, buffer, len, 0, (struct sockaddr *) &amp;remote, sizeof(remote)) &lt; 0)
      {
          perror ("sendto");
          printf ("Error while sending packet.\n");
      }
  }
  </code></pre>
  
  <p>I've debugged the program and all the values in the ip6_hdr struct seem to be correct and also the ones in the struct UDP_hdr. Am I missing something?</p>