title: C Networking: Sendto() returning Errno 22, EINVAL
body: <p>I'm attempting to generate a packet from scratch with Layer 2, 3, and 4 components (namely Ethernet, IP, and UDP). My socket is configured to use SOCK_RAW as the type and IPPROTO_RAW as the protocol, so that my program can be used to send different protocols at a later date. I've strictly abided by the sendto(2) man page (<a href="https://linux.die.net/man/2/sendto" rel="nofollow noreferrer">https://linux.die.net/man/2/sendto</a>), however, I still seem to be having troubles transmitting a packet over local host. The error returned by my program is 22, or EINVAL, indicating that I've passed an incorrect argument.</p>
  
  <p>I've already used <a href="https://stackoverflow.com/questions/22977839/sockets-sendto-returning-einval">Sockets sendto() returning EINVAL</a> and <a href="https://stackoverflow.com/questions/4006786/socket-programming-sendto-always-fails-with-errno-22-einval">Socket programming: sendto always fails with errno 22 (EINVAL)</a> in attempt to resolve my problem. I've even switched the socket to use SOCK_DGRAM as the type and IPPROTO_UDP as the protocol to see if it was something to do with the socket (though I don't believe this would have prompted an incorrect argument response). </p>
  
  <p>My code is as follows:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;string.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;netinet/ip.h&gt;
  #include &lt;netinet/ether.h&gt;
  #include &lt;netinet/udp.h&gt;
  #include &lt;sys/socket.h&gt;
  #include &lt;errno.h&gt;
  
  #define BUFFER 1024
  
  int main(int argc, char *argv[]) {
  
          /* Socket Creation */
      int sockfd;
  
      if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) {
              perror("Socket");
              exit(EXIT_FAILURE);
      }
  
      // This will hold all of the packet's contents
      char sendbuf[BUFFER];
  
  
      /* Address Stuff */
  
      // Specify Address
      in_addr_t address = inet_addr("127.0.0.1");
  
      // Specifying Address for Sendto()
      struct sockaddr_in sendto_addr;
      memset(&amp;sendto_addr, 0, sizeof(sendto_addr));
      sendto_addr.sin_family = AF_INET;
      sendto_addr.sin_port = htons(9623);  // Make sure the port isn't contested
      sendto_addr.sin_addr.s_addr = address;
  
      // Size of whole packet
      size_t total_len = 0;
  
  
      /* LAYER 2 */
      // Ethernet Header Configuration
      struct ether_header *ether = (struct ether_header *)sendbuf;
      int i;
      for (i = 0; i &lt; 6; ++i) {
          ether -&gt; ether_dhost[i] = 0x00; // Temporary data fill
          ether -&gt; ether_shost[i] = 0x00; // Temporary data fill
      }
      ether -&gt; ether_type = ETHERTYPE_IP;
  
      total_len += sizeof(struct ether_header);
  
  
      /* LAYER 3 */
      // IP Header Configuration
      struct ip *ip = (struct ip *)(sendbuf + sizeof(struct ether_header));
  
      ip -&gt; ip_hl = 5;
      ip -&gt; ip_v = 4;
      ip -&gt; ip_tos = 0;
      ip -&gt; ip_p = 17;
      ip -&gt; ip_ttl = 255;
      ip -&gt; ip_src.s_addr = address;
      ip -&gt; ip_dst.s_addr = address;  
  
      total_len += sizeof(struct ip); 
  
  
      /* LAYER 4 */
      // UDP Header Configuration
      struct udphdr *udp = (struct udphdr *)(sendbuf + sizeof(struct ether_header) + \
                                             sizeof(struct ip));
  
      udp -&gt; source = 123; // Gibberish to fill in later
      udp -&gt; dest = 321;   // Gibberish to fill in later
      udp -&gt; check = 0;
  
      total_len += sizeof(struct udphdr);
  
  
      /* Giberrish Packet Data */
      sendbuf[total_len++] = 0x00;
      sendbuf[total_len++] = 0x00;
      sendbuf[total_len++] = 0x00;
      sendbuf[total_len++] = 0x00;
  
  
      /* Fill in Rest of Headers */
      udp -&gt; len = htons(total_len - sizeof(struct ether_header) - sizeof(struct ip));
      ip -&gt; ip_len = htons(total_len - sizeof(struct ether_header));
  
  
      /* Send Packet */  // ERROR OCCURS HERE
      printf("Sockfd is %d\n", sockfd);
      printf("Total length is %d\n", total_len);
      if (sendto(sockfd, sendbuf, total_len, 0, (const struct sockaddr*)&amp;sendto_addr, \
          sizeof(sendto_addr)) &lt; 0) {
              printf("Error sending packet: Error %d.\n", errno);
              perror("sendto Error");
              exit(EXIT_FAILURE);
      } 
  
      close(sockfd);
  
  }
  </code></pre>
  
  <p>The precise console message states:  </p>
  
  <blockquote>
    <p>Sockfd is 3<br>
        Total length is 46<br>
        Error sending packet: Error 22.<br>
        sendto Error: Invalid argument</p>
  </blockquote>