title: Despite RAW socket and HDRINCL, IP source address is still filled by system
body: <p>I'm writing simple DHCP client so, according to the RFC 951, I need to send packets with IP source address = "0.0.0.0". As I know it is possible using RAW sockets, but apparently something in my code is wrong - source address is always filled by kernel (to the defined address of other interface).</p>
  
  <pre class="lang-c prettyprint-override"><code>   if (sockfd==0)
      {
          sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
          if (sockfd&lt;0)
          {
              return result.setError(-1, "Can't create socket.");
          }
          status = setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, m_ifName, strlen(m_ifName));
          if (status&lt;0)
          {
              return result.setError(status, "Can't bind socket to the interface.");
          }
  
          int optVal = 1;
          status = setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &amp;optVal, sizeof(optVal));
          if (status != 0)
          {
              return result.setError(status, "Can't set IP_HDRINCL option on a socket");
          }
  
          int broadcastVal = 1;
          status = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
                              reinterpret_cast&lt;const void*&gt;(&amp;broadcastVal), sizeof(broadcastVal));
          if (status!=0)
          {
              return result.setError(status, "Can't set a broadcast option on a socket.");
          }
  
          int reuseAddrVal = 1;
          status = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &amp;reuseAddrVal, sizeof(reuseAddrVal));
          if(status != 0)
              return result.setError(status, "Can't set a SO_REUSEADDR opt on socket.");
  
          struct sockaddr_in src_addr;
          src_addr.sin_family = AF_INET;
          src_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
          src_addr.sin_port = htons(sourcePort);
          status = bind(sockfd, reinterpret_cast&lt;sockaddr *&gt;(&amp;src_addr), sizeof(sockaddr_in));
          if (status != 0)
          {
              return result.setError(status, "Can't bind to the socket.");
          }
      }
  
      unsigned char buffer[8192];
      struct sockaddr_in dest_addr;
      char* packetData = (char*)(buffer + sizeof(struct ip) + sizeof(struct udphdr));
      struct ip* ip_header = (struct ip*) buffer;
      struct udphdr* udp_header = (struct udphdr*) (buffer + sizeof(struct ip));
  
      memset(buffer, 0, sizeof(buffer));
      memset(&amp;dest_addr, 0, sizeof(dest_addr));
  
      dest_addr.sin_family = AF_INET;
      dest_addr.sin_addr.s_addr = INADDR_BROADCAST;
      dest_addr.sin_port = htons(67);
  
      ip_header-&gt;ip_v = 4;
      ip_header-&gt;ip_hl = 5;
      ip_header-&gt;ip_tos = 0;
      ip_header-&gt;ip_id = 0;
      ip_header-&gt;ip_ttl = 63;
      ip_header-&gt;ip_p = IPPROTO_UDP;
      ip_header-&gt;ip_off = 0;
      ip_header-&gt;ip_sum = 0;
      ip_header-&gt;ip_src.s_addr = inet_addr("0.0.0.0");
      ip_header-&gt;ip_dst.s_addr = htonl(INADDR_BROADCAST);
  
      udp_header-&gt;source = htons(68);
      udp_header-&gt;dest = htons(67);
      udp_header-&gt;check = htons(0);
  
      DhcpData data(sizeof(DhcpHdr), 0);
      prepareDhcpPacket(type, data, result);
      if (result.errCode != 0)
      {
          return result;
      }
      strcpy(packetData, (const char*) data.constData());
  
      ip_header-&gt;ip_len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + data.size());
      udp_header-&gt;len = htons(sizeof(struct udphdr) + data.size());
  
      ip_header-&gt;ip_sum = ComputeChecksum((unsigned char *)ip_header, ip_header-&gt;ip_hl*4);
  
      int segment_len = (sizeof(struct iphdr) + sizeof(struct udphdr) + data.size()) - ip_header-&gt;ip_hl*4;
      int header_len = sizeof(PseudoHeader) + segment_len;
  
      unsigned char* hdr = (unsigned char *)malloc(header_len);
      PseudoHeader* pseudo_header;
      pseudo_header = (PseudoHeader *)hdr;
      pseudo_header-&gt;source_ip = ip_header-&gt;ip_src.s_addr;
      pseudo_header-&gt;dest_ip = ip_header-&gt;ip_dst.s_addr;
      pseudo_header-&gt;reserved = 0;
      pseudo_header-&gt;protocol = ip_header-&gt;ip_p;
      pseudo_header-&gt;udp_length = htons(segment_len);
  
      memcpy((hdr + sizeof(PseudoHeader)), (void *)udp_header, 8);
      memcpy((hdr + sizeof(PseudoHeader) + 8), packetData, data.size());
      udp_header-&gt;check = ComputeChecksum(hdr, header_len);
  
      free(hdr);
  
      int res = sendto(sockfd, buffer, (sizeof(struct ip) + sizeof(struct udphdr) + data.size()), 0, (struct sockaddr *)&amp;dest_addr, sizeof(dest_addr));
      if(res &lt; 0)
      {
          printf("Errno=%s", strerror(errno));
      }
  
  /* taken from TCP/IP Illustrated Vol. 2(1995) by Gary R. Wright and W. Richard Stevens. Page 236 */
  unsigned short ComputeChecksum(unsigned char *data, int len)
  {
      long sum = 0;  /* assume 32 bit long, 16 bit short */
      unsigned short *temp = (unsigned short *)data;
  
      while(len &gt; 1){
          sum += *temp++;
          if(sum &amp; 0x80000000)   /* if high order bit set, fold */
              sum = (sum &amp; 0xFFFF) + (sum &gt;&gt; 16);
          len -= 2;
      }
  
      if(len)       /* take care of left over byte */
          sum += (unsigned short) *((unsigned char *)temp);
  
      while(sum&gt;&gt;16)
          sum = (sum &amp; 0xFFFF) + (sum &gt;&gt; 16);
  
      return ~sum;
  }
  </code></pre>