title: Creating RAW Packets with Go 1.5 on MacOSX
body: <p>I am trying to do some basic packet crafting for a testing tool I am working on, but I can not seem to get the packet crafting to work (I am using Go 1.5 on OSX  and am running as root.) </p>
  
  <p>I am using the following code (<a href="http://www.darkcoding.net/software/raw-sockets-in-go-link-layer/" rel="nofollow noreferrer">taken from here</a>) to try and create an ICMP packet, but when I try to specify say specific options in the IP header it does not seem to work.  Further when I look at this packet in wireshark it shows up as protocol 255 (unknown).  </p>
  
  <p>I have read that on Linux system you can use AF_PACKET but on OSX systems you need to use BPF, however the sample code I found is using "syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW)" and I am not sure how to get started with BPF.  I have also seen some people try to use gopacket instead of the x/net/ipv4 package.  </p>
  
  <pre><code>package main
  
  import (
      "golang.org/x/net/ipv4"
      "net"
      "syscall"
  )
  
  func main() {
      var err error
      fd, _ := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
  
      addr := syscall.SockaddrInet4{
          Port: 0,
          Addr: [4]byte{127, 0, 0, 1},
      }
      p := pkt()
  
      _ = syscall.Sendto(fd, p, 0, &amp;addr)
  }
  
  func pkt() []byte {
      h := ipv4.Header{
          Version:  4,
          Len:      20,
          TOS:      0,
          TotalLen: 85, // I can not seem to change this
          ID:       2,  // I can not seem to change this
          TTL:      64, // I can not seem to change this
          Protocol: 1,  // ICMP, This does not seem to work
          Dst:      net.IPv4(127, 0, 0, 1),
      }
  
      icmp := []byte{
          8, // type: echo request
          0, // code: not used by echo request
          0, // checksum (16 bit), we fill in below
          0,
          0, // identifier (16 bit). zero allowed.
          0,
          0, // sequence number (16 bit). zero allowed.
          0,
          0xC0, // Optional data. ping puts time packet sent here
          0xDE,
      }
      cs := csum(icmp)
      icmp[2] = byte(cs)
      icmp[3] = byte(cs &gt;&gt; 8)
  
      out, _ := h.Marshal()
  
      return append(out, icmp...)
  }
  
  func csum(b []byte) uint16 {
      var s uint32
      for i := 0; i &lt; len(b); i += 2 {
          s += uint32(b[i+1])&lt;&lt;8 | uint32(b[i])
      }
      // add back the carry
      s = s&gt;&gt;16 + s&amp;0xffff
      s = s + s&gt;&gt;16
      return uint16(^s)
  }
  </code></pre>
  
  <p>If I print out the p variable that contains the packet data in Main() after the data comes back from pkt() it looks right:</p>
  
  <pre><code>DEBUG: (decimal) [69 0 60 0 0 0 0 0 64 1 0 0 0 0 0 0 127 0 0 1 8 0 55 33 0 0 0 0 192 222]
  DEBUG: (hex)      45 0 3c 0 0 0 0 0 40 1 0 0 0 0 0 0 7f 0 0 1 8 0 37 21 0 0 0 0 c0 de 
  </code></pre>
  
  <p>And you can see that the protocol is set for "1" in the 10th byte.  But when we look at this packet in wireshark it looks like:</p>
  
  <p><a href="https://i.stack.imgur.com/oTg5f.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/oTg5f.png" alt="wireshark screen shot"></a></p>