func main() { // Open device handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout) if err != nil { log.Fatal(err) } defer handle.Close() // Send raw bytes over wire rawBytes := []byte{10, 20, 30} err = handle.WritePacketData(rawBytes) if err != nil { log.Fatal(err) } // Create a properly formed packet, just with // empty details. Should fill out MAC addresses, // IP addresses, etc. buffer = gopacket.NewSerializeBuffer() gopacket.SerializeLayers(buffer, options, &layers.Ethernet{}, &layers.IPv4{}, &layers.TCP{}, gopacket.Payload(rawBytes), ) outgoingPacket := buffer.Bytes() // Send our packet err = handle.WritePacketData(outgoingPacket) if err != nil { log.Fatal(err) } // This time lets fill out some information ipLayer := &layers.IPv4{ SrcIP: net.IP{127, 0, 0, 1}, DstIP: net.IP{8, 8, 8, 8}, } ethernetLayer := &layers.Ethernet{ SrcMAC: net.HardwareAddr{0xFF, 0xAA, 0xFA, 0xAA, 0xFF, 0xAA, 0xFA, 0xAA}, DstMAC: net.HardwareAddr{0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD}, } tcpLayer := &layers.TCP{ SrcPort: layers.TCPPort(4321), DstPort: layers.TCPPort(80), } // And create the packet with the layers buffer = gopacket.NewSerializeBuffer() gopacket.SerializeLayers(buffer, options, ethernetLayer, ipLayer, tcpLayer, gopacket.Payload(rawBytes), ) outgoingPacket = buffer.Bytes() }
func (sender *RawUDPSender) Send(msg []byte) error { payload := gopacket.Payload(msg) sender.udpHeader.DstPort = layers.UDPPort(sender.conn.RemoteUDPAddr().Port) err := gopacket.SerializeLayers(sender.ipBuf, sender.opts, sender.udpHeader, &payload) if err != nil { return err } packet := sender.ipBuf.Bytes() _, err = sender.socket.Write(packet) if err == nil || PosixError(err) != syscall.EMSGSIZE { return err } f, err := sender.socket.File() if err != nil { return err } defer f.Close() fd := int(f.Fd()) log.Println("EMSGSIZE on send, expecting PMTU update (IP packet was", len(packet), "bytes, payload was", len(msg), "bytes)") pmtu, err := syscall.GetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_MTU) if err != nil { return err } return MsgTooBigError{PMTU: pmtu} }
func newIcmpData(src, dest *net.IPAddr, typeCode, offSet, ttl int) (data []byte) { ip := &layers.IPv4{} ip.Version = 4 ip.Protocol = layers.IPProtocolICMPv4 ip.SrcIP = src.IP ip.DstIP = dest.IP ip.Length = 20 ip.TTL = uint8(ttl) icmp := &layers.ICMPv4{} icmp.TypeCode = layers.ICMPv4TypeCode(uint16(typeCode) << 8) icmp.Id = pid icmp.Seq = 1 icmp.Checksum = 0 opts := gopacket.SerializeOptions{} opts.ComputeChecksums = true opts.FixLengths = true now := time.Now().UnixNano() var payload = make([]byte, 8) binary.LittleEndian.PutUint64(payload, uint64(now)) buf := gopacket.NewSerializeBuffer() gopacket.SerializeLayers(buf, opts, ip, icmp, gopacket.Payload(payload)) return buf.Bytes() }
func TestSetupPan(t *testing.T) { /* packetManifest := types.PacketManifest{ Timestamp: time.Now(), Flow: nil, RawPacket: nil, IP: ip, TCP: tcp, Payload: payload, } */ buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{} ip0 := net.ParseIP("127.0.0.100") ip1 := net.ParseIP("127.0.0.1") gopacket.SerializeLayers(buf, opts, &layers.Ethernet{}, &layers.IPv4{SrcIP: ip0, DstIP: ip1}, &layers.TCP{}, gopacket.Payload([]byte{1, 2, 3, 4, 5})) packetData := buf.Bytes() assert.NotEqual(t, packetData, nil) }
func forgeEthIPTCP(t *testing.T, seed int64) *gopacket.Packet { var options gopacket.SerializeOptions rnd := rand.New(rand.NewSource(seed)) rawBytes := []byte{10, 20, 30} ethernetLayer := &layers.Ethernet{ SrcMAC: net.HardwareAddr{0x00, 0x0F, 0xAA, 0xFA, 0xAA, byte(rnd.Intn(0x100))}, DstMAC: net.HardwareAddr{0x00, 0x0D, 0xBD, 0xBD, byte(rnd.Intn(0x100)), 0xBD}, } ipLayer := &layers.IPv4{ SrcIP: net.IP{127, 0, 0, byte(rnd.Intn(0x100))}, DstIP: net.IP{byte(rnd.Intn(0x100)), 8, 8, 8}, } tcpLayer := &layers.TCP{ SrcPort: layers.TCPPort(byte(rnd.Intn(0x10000))), DstPort: layers.TCPPort(byte(rnd.Intn(0x10000))), } // And create the packet with the layers buffer := gopacket.NewSerializeBuffer() err := gopacket.SerializeLayers(buffer, options, ethernetLayer, ipLayer, tcpLayer, gopacket.Payload(rawBytes), ) if err != nil { t.Fail() } gpacket := gopacket.NewPacket(buffer.Bytes(), layers.LayerTypeEthernet, gopacket.Default) return &gpacket }
func (dec *EthernetDecoder) sendICMPFragNeeded(mtu int, sendFrame func([]byte) error) error { buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true} ipHeaderSize := int(dec.IP.IHL) * 4 // IHL is the number of 32-byte words in the header payload := gopacket.Payload(dec.IP.BaseLayer.Contents[:ipHeaderSize+8]) err := gopacket.SerializeLayers(buf, opts, &layers.Ethernet{ SrcMAC: dec.Eth.DstMAC, DstMAC: dec.Eth.SrcMAC, EthernetType: dec.Eth.EthernetType}, &layers.IPv4{ Version: 4, TOS: dec.IP.TOS, Id: 0, Flags: 0, FragOffset: 0, TTL: 64, Protocol: layers.IPProtocolICMPv4, DstIP: dec.IP.SrcIP, SrcIP: dec.IP.DstIP}, &layers.ICMPv4{ TypeCode: 0x304, Id: 0, Seq: uint16(mtu)}, &payload) if err != nil { return err } Log.Printf("Sending ICMP 3,4 (%v -> %v): PMTU= %v\n", dec.IP.DstIP, dec.IP.SrcIP, mtu) return sendFrame(buf.Bytes()) }
func main() { // If we don't have a handle to a device or a file, but we have a bunch // of raw bytes, we can try to decode them in to packet information // NewPacket() takes the raw bytes that make up the packet as the first parameter // The second parameter is the lowest level layer you want to decode. It will // decode that layer and all layers on top of it. The third layer // is the type of decoding: default(all at once), lazy(on demand), and NoCopy // which will not create a copy of the buffer // Create an packet with ethernet, IP, TCP, and payload layers // We are creating one we know will be decoded properly but // your byte source could be anything. If any of the packets // come back as nil, that means it could not decode it in to // the proper layer (malformed or incorrect packet type) payload := []byte{2, 4, 6} options := gopacket.SerializeOptions{} buffer := gopacket.NewSerializeBuffer() gopacket.SerializeLayers(buffer, options, &layers.Ethernet{}, &layers.IPv4{}, &layers.TCP{}, gopacket.Payload(payload), ) rawBytes := buffer.Bytes() // Decode an ethernet packet ethPacket := gopacket.NewPacket( rawBytes, layers.LayerTypeEthernet, gopacket.Default, ) // with Lazy decoding it will only decode what it needs when it needs it // This is not concurrency safe. If using concurrency, use default ipPacket := gopacket.NewPacket( rawBytes, layers.LayerTypeIPv4, gopacket.Lazy, ) // With the NoCopy option, the underlying slices are referenced // directly and not copied. If the underlying bytes change so will // the packet tcpPacket := gopacket.NewPacket( rawBytes, layers.LayerTypeTCP, gopacket.NoCopy, ) fmt.Println(ethPacket) fmt.Println(ipPacket) fmt.Println(tcpPacket) }
/* protos must contain a UDP or TCP layer on top of IPv4 */ func forgeTestPacket(t *testing.T, seed int64, protos ...ProtocolType) *gopacket.Packet { rnd := rand.New(rand.NewSource(seed)) rawBytes := []byte{10, 20, 30} var protoStack []gopacket.SerializableLayer for i, proto := range protos { switch proto { case ETH: ethernetLayer := &layers.Ethernet{ SrcMAC: net.HardwareAddr{0x00, 0x0F, 0xAA, 0xFA, 0xAA, byte(rnd.Intn(0x100))}, DstMAC: net.HardwareAddr{0x00, 0x0D, 0xBD, 0xBD, byte(rnd.Intn(0x100)), 0xBD}, EthernetType: layers.EthernetTypeIPv4, } protoStack = append(protoStack, ethernetLayer) case IPv4: ipv4Layer := &layers.IPv4{ SrcIP: net.IP{127, 0, 0, byte(rnd.Intn(0x100))}, DstIP: net.IP{byte(rnd.Intn(0x100)), 8, 8, 8}, } switch protos[i+1] { case TCP: ipv4Layer.Protocol = layers.IPProtocolTCP case UDP: ipv4Layer.Protocol = layers.IPProtocolUDP } protoStack = append(protoStack, ipv4Layer) case TCP: tcpLayer := &layers.TCP{ SrcPort: layers.TCPPort(byte(rnd.Intn(0x10000))), DstPort: layers.TCPPort(byte(rnd.Intn(0x10000))), } protoStack = append(protoStack, tcpLayer) case UDP: udpLayer := &layers.UDP{ SrcPort: layers.UDPPort(byte(rnd.Intn(0x10000))), DstPort: layers.UDPPort(byte(rnd.Intn(0x10000))), } protoStack = append(protoStack, udpLayer) default: t.Log("forgeTestPacket : Unsupported protocol ", proto) } } protoStack = append(protoStack, gopacket.Payload(rawBytes)) buffer := gopacket.NewSerializeBuffer() options := gopacket.SerializeOptions{FixLengths: true} err := gopacket.SerializeLayers(buffer, options, protoStack...) if err != nil { t.Fail() } gpacket := gopacket.NewPacket(buffer.Bytes(), layers.LayerTypeEthernet, gopacket.Default) return &gpacket }
func fragment(eth layers.Ethernet, ip layers.IPv4, mtu int, forward func([]byte)) error { // We are not doing any sort of NAT, so we don't need to worry // about checksums of IP payload (eg UDP checksum). headerSize := int(ip.IHL) * 4 // &^ is bit clear (AND NOT). So here we're clearing the lowest 3 // bits. maxSegmentSize := (mtu - headerSize) &^ 7 opts := gopacket.SerializeOptions{ FixLengths: false, ComputeChecksums: true} payloadSize := int(ip.Length) - headerSize payload := ip.BaseLayer.Payload[:payloadSize] offsetBase := int(ip.FragOffset) << 3 origFlags := ip.Flags ip.Flags = ip.Flags | layers.IPv4MoreFragments ip.Length = uint16(headerSize + maxSegmentSize) if eth.EthernetType == layers.EthernetTypeLLC { // using LLC, so must set eth length correctly. eth length // is just the length of the payload eth.Length = ip.Length } else { eth.Length = 0 } for offset := 0; offset < payloadSize; offset += maxSegmentSize { var segmentPayload []byte if len(payload) <= maxSegmentSize { // last one segmentPayload = payload ip.Length = uint16(len(payload) + headerSize) ip.Flags = origFlags if eth.EthernetType == layers.EthernetTypeLLC { eth.Length = ip.Length } else { eth.Length = 0 } } else { segmentPayload = payload[:maxSegmentSize] payload = payload[maxSegmentSize:] } ip.FragOffset = uint16((offset + offsetBase) >> 3) buf := gopacket.NewSerializeBuffer() segPayload := gopacket.Payload(segmentPayload) err := gopacket.SerializeLayers(buf, opts, ð, &ip, &segPayload) if err != nil { return err } forward(buf.Bytes()) } return nil }
func TestIPv6JumbogramUDPChecksum(t *testing.T) { var serialize []gopacket.SerializableLayer = make([]gopacket.SerializableLayer, 0, 4) var u *UDP var err error ip6 := &IPv6{} ip6.Version = 6 ip6.NextHeader = IPProtocolUDP ip6.HopLimit = 64 ip6.SrcIP = net.ParseIP("2001:db8::1") ip6.DstIP = net.ParseIP("2001:db8::2") serialize = append(serialize, ip6) udp := &UDP{} udp.SrcPort = UDPPort(12345) udp.DstPort = UDPPort(9999) udp.SetNetworkLayerForChecksum(ip6) serialize = append(serialize, udp) payload := make([]byte, ipv6MaxPayloadLength+1) for i := range payload { payload[i] = 0xfe } serialize = append(serialize, gopacket.Payload(payload)) buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{FixLengths: true, ComputeChecksums: true} err = gopacket.SerializeLayers(buf, opts, serialize...) if err != nil { t.Fatal(err) } p := gopacket.NewPacket(buf.Bytes(), LinkTypeRaw, gopacket.Default) if p.ErrorLayer() != nil { t.Fatal("Failed to decode packet:", p.ErrorLayer().Error()) } checkLayers(p, []gopacket.LayerType{LayerTypeIPv6, LayerTypeIPv6HopByHop, LayerTypeUDP, gopacket.LayerTypePayload}, t) if l, ok := p.Layer(LayerTypeUDP).(*UDP); !ok { t.Fatal("No UDP layer type found in packet") } else { u = l } got := u.Checksum want := ipv6UDPChecksumJumbogram if got != want { t.Errorf("Bad checksum:\ngot:\n%#v\n\nwant:\n%#v\n\n", got, want) } }
func TestGetOverlapRingsWithZeroRings(t *testing.T) { ip := layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp := layers.TCP{ SYN: true, SrcPort: 1, DstPort: 2, } tcp.SetNetworkLayerForChecksum(&ip) payload := gopacket.Payload([]byte{1, 2, 3, 4}) p := types.PacketManifest{ IP: ip, TCP: tcp, Payload: payload, } options := ConnectionOptions{ MaxBufferedPagesTotal: 0, MaxBufferedPagesPerConnection: 0, MaxRingPackets: 40, PageCache: nil, LogDir: "fake-log-dir", } f := &DefaultConnFactory{} conn := f.Build(options).(*Connection) ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) serverFlow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow) clientFlow := serverFlow.Reverse() conn.serverFlow = serverFlow conn.clientFlow = clientFlow head, tail := getOverlapRings(&p, serverFlow, conn.ClientStreamRing) if head == nil || tail == nil { return } else { t.Fail() } return }
func sendPacket(handle *pcap.Handle, sMac, dMac net.HardwareAddr, sIp, dIp net.IP, sPort, dPort layers.TCPPort, IpId uint16, IpTtl uint8, TcpSeq, ack uint32, WindowsSize uint16, data []byte) error { eth := layers.Ethernet{ SrcMAC: sMac, DstMAC: dMac, EthernetType: layers.EthernetTypeIPv4, } ip4 := layers.IPv4{ SrcIP: sIp, DstIP: dIp, Id: IpId, Flags: layers.IPv4DontFragment, Version: 4, TTL: IpTtl, Protocol: layers.IPProtocolTCP, } tcp := layers.TCP{ SrcPort: sPort, DstPort: dPort, Seq: TcpSeq, ACK: true, Ack: ack, Window: WindowsSize, PSH: true, // 立刻处理 } if len(data) == 0 { tcp.RST = true } tcp.SetNetworkLayerForChecksum(&ip4) buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } payload := gopacket.Payload(data) if err := gopacket.SerializeLayers(buf, opts, ð, &ip4, &tcp, payload); err != nil { return err } return handle.WritePacketData(buf.Bytes()) }
/* FUNCTION: craftPacket(data []byte, ip string, port uint16, payload []byte) []byte RETURNS: []byte, byte array containing packet data created ARGUMENTS: []byte data - data to be placed in the source port string ip - address to place in the dst ip of the ip layer uint16 port - destination port of udp header []byte payload - udp payload to be passed in ABOUT: Crafts a packet with a IP, ethernet and UDP header. Covertly inserts data into the source port and appends the specified payload. */ func craftPacket(data []byte, ip string, port uint16, payload []byte) []byte { ethernetLayer := &layers.Ethernet{ SrcMAC: localmac, DstMAC: destmac, EthernetType: layers.EthernetTypeIPv4, } ipLayer := &layers.IPv4{ Version: 4, IHL: 5, TOS: 0, Length: 20, Id: 2, Flags: layers.IPv4DontFragment, FragOffset: 0, TTL: 255, Protocol: layers.IPProtocolUDP, Checksum: 0, SrcIP: localip, DstIP: net.ParseIP(ip), } val := binary.BigEndian.Uint16(data) udpLayer := &layers.UDP{ SrcPort: layers.UDPPort(MAX_PORT - val), DstPort: layers.UDPPort(port), Length: 16, } err := udpLayer.SetNetworkLayerForChecksum(ipLayer) checkError(err) buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } err = gopacket.SerializeLayers(buf, opts, ethernetLayer, ipLayer, udpLayer, gopacket.Payload(payload)) checkError(err) return buf.Bytes() }
func main() { // Open device handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout) if err != nil { log.Fatal(err) } defer handle.Close() // Create the layers ethernetLayer := &layers.Ethernet{ SrcMAC: net.HardwareAddr{0xFF, 0xAA, 0xFA, 0xAA, 0xFF, 0xAA}, DstMAC: net.HardwareAddr{0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD}, EthernetType: layers.EthernetTypeIPv4, } ipLayer := &layers.IPv4{ SrcIP: net.IP{192, 168, 1, 3}, DstIP: net.IP{8, 8, 8, 8}, Version: 4, IHL: 5, // 20 bytes standard header size Length: 24, } tcpLayer := &layers.TCP{ SrcPort: layers.TCPPort(4321), DstPort: layers.TCPPort(80), } payload := []byte{10, 20, 30, 40} // Serialize the layers buffer = gopacket.NewSerializeBuffer() gopacket.SerializeLayers(buffer, options, ethernetLayer, ipLayer, tcpLayer, gopacket.Payload(payload), ) outgoingPacket := buffer.Bytes() // Send packet over the wire (or air) err = handle.WritePacketData(outgoingPacket) if err != nil { log.Fatal(err) } }
func (vnet *VNET) handleICMPv4EchoRequest(pkt *Packet) { host := vnet.hosts.GetTable().LookupByIPv4(pkt.IPv4.DstIP) if host == nil { log.Printf("ICMPv4: DST: %s (unknown)\n", pkt.IPv4.DstIP) return } if !host.Up { log.Printf("ICMPv4: DST: %s (down)\n", pkt.IPv4.DstIP) return } if len(host.IPv4Addrs) == 0 { log.Printf("ICMPv4: DST: %s (unknown)\n", pkt.IPv4.DstIP) return } log.Printf("ICMPv4: DST: %s (up)\n", pkt.IPv4.DstIP) err := vnet.writePacket( &layers.Ethernet{ SrcMAC: vnet.system.ControllerMAC(), DstMAC: pkt.Eth.SrcMAC, EthernetType: layers.EthernetTypeIPv4, }, &layers.IPv4{ SrcIP: pkt.IPv4.DstIP, DstIP: pkt.IPv4.SrcIP, Version: 4, Protocol: layers.IPProtocolICMPv4, TTL: 64, }, &layers.ICMPv4{ TypeCode: layers.ICMPv4TypeEchoReply << 8, Seq: pkt.ICMPv4.Seq, Id: pkt.ICMPv4.Id, BaseLayer: layers.BaseLayer{ Contents: pkt.ICMPv4.Contents, }, }, gopacket.Payload(pkt.ICMPv4.Payload)) if err != nil { log.Printf("DCHP/error: %s", err) return } }
func (r *RawSocketServer) injectPacketFromDst(tcpLayer *layers.TCP, rawBytes []byte) error { // Preparing ipLayer. ipLayer := &layers.IPv4{ SrcIP: r.dst.ip, DstIP: r.src.ip, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } options := gopacket.SerializeOptions{ ComputeChecksums: true, FixLengths: true, } tcpLayer.SrcPort = r.dst.port tcpLayer.DstPort = r.src.port tcpLayer.Window = r.window tcpLayer.Ack = r.ack tcpLayer.Seq = r.seq tcpLayer.SetNetworkLayerForChecksum(ipLayer) // And create the packet with the layers buffer := gopacket.NewSerializeBuffer() gopacket.SerializeLayers(buffer, options, ipLayer, tcpLayer, gopacket.Payload(rawBytes), ) outgoingPacket := buffer.Bytes() p := tuntap.Packet{ Protocol: 0x800, Truncated: false, Packet: outgoingPacket, } return r.iface.WritePacket(&p) }
func packet(raddr net.IP) []byte { ip := &layers.IPv4{ Version: 0x4, TOS: 0x0, TTL: 0x40, Protocol: layers.IPProtocolUDP, SrcIP: net.ParseIP(os.Args[2]), DstIP: raddr, WithRawINETSocket: true, } udp := &layers.UDP{ SrcPort: 0xaa47, DstPort: 0x50, } udp.SetNetworkLayerForChecksum(ip) buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{true, true} check(gopacket.SerializeLayers(buf, opts, ip, udp, gopacket.Payload([]byte("gg ez")))) return buf.Bytes() }
func (sender *udpSenderDF) send(msg []byte, raddr *net.UDPAddr) error { // Ensure we have a socket sending to the right IP address if sender.socket == nil || !bytes.Equal(sender.remoteIP, raddr.IP) { sender.remoteIP = raddr.IP if err := sender.dial(); err != nil { return err } } sender.udpHeader.DstPort = layers.UDPPort(raddr.Port) payload := gopacket.Payload(msg) err := gopacket.SerializeLayers(sender.ipBuf, sender.opts, sender.udpHeader, &payload) if err != nil { return err } packet := sender.ipBuf.Bytes() _, err = sender.socket.Write(packet) if err == nil || PosixError(err) != syscall.EMSGSIZE { return err } f, err := sender.socket.File() if err != nil { return err } defer f.Close() log.Print("EMSGSIZE on send, expecting PMTU update (IP packet was ", len(packet), " bytes, payload was ", len(msg), " bytes)") pmtu, err := syscall.GetsockoptInt(int(f.Fd()), syscall.IPPROTO_IP, syscall.IP_MTU) if err != nil { return err } return msgTooBigError{underlayPMTU: pmtu} }
func TestIPv6JumbogramSerialize(t *testing.T) { var serialize []gopacket.SerializableLayer = make([]gopacket.SerializableLayer, 0, 2) var err error ip6 := &IPv6{} ip6.Version = 6 ip6.NextHeader = IPProtocolNoNextHeader ip6.HopLimit = 64 ip6.SrcIP = net.ParseIP("2001:db8::1") ip6.DstIP = net.ParseIP("2001:db8::2") serialize = append(serialize, ip6) payload := make([]byte, ipv6MaxPayloadLength+1) for i := range payload { payload[i] = 0xfe } serialize = append(serialize, gopacket.Payload(payload)) buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{FixLengths: true} err = gopacket.SerializeLayers(buf, opts, serialize...) if err != nil { t.Fatal(err) } got := buf.Bytes() w := new(bytes.Buffer) w.Write(testPacketIPv6JumbogramHeader) w.Write(payload) want := w.Bytes() if !bytes.Equal(got, want) { t.Errorf("IPv6 Jumbogram serialize failed:\ngot:\n%v\n\nwant:\n%v\n\n", gopacket.LongBytesGoString(got), gopacket.LongBytesGoString(want)) } }
/* protos must contain a UDP or TCP layer on top of IPv4 */ func forgeTestPacket(t *testing.T, seed int64, swap bool, protos ...ProtocolType) *gopacket.Packet { rnd := rand.New(rand.NewSource(seed)) rawBytes := []byte{10, 20, 30} var protoStack []gopacket.SerializableLayer for i, proto := range protos { switch proto { case GRE: greLayer := &layers.GRE{} switch protos[i+1] { case IPv4: greLayer.Protocol = layers.EthernetTypeIPv4 case IPv6: greLayer.Protocol = layers.EthernetTypeIPv6 default: t.Error(fmt.Sprintf("Protocol %s can not be encapsulated in GRE", protos[i+1])) } protoStack = append(protoStack, greLayer) case ETH: ethernetLayer := &layers.Ethernet{ SrcMAC: net.HardwareAddr{0x00, 0x0F, 0xAA, 0xFA, 0xAA, byte(rnd.Intn(0x100))}, DstMAC: net.HardwareAddr{0x00, 0x0D, 0xBD, 0xBD, byte(rnd.Intn(0x100)), 0xBD}, EthernetType: layers.EthernetTypeIPv4, } if swap { ethernetLayer.SrcMAC, ethernetLayer.DstMAC = ethernetLayer.DstMAC, ethernetLayer.SrcMAC } protoStack = append(protoStack, ethernetLayer) case IPv4: ipv4Layer := &layers.IPv4{ SrcIP: net.IP{127, 0, 0, byte(rnd.Intn(0x100))}, DstIP: net.IP{byte(rnd.Intn(0x100)), 8, 8, 8}, } switch protos[i+1] { case TCP: ipv4Layer.Protocol = layers.IPProtocolTCP case UDP: ipv4Layer.Protocol = layers.IPProtocolUDP case GRE: ipv4Layer.Protocol = layers.IPProtocolGRE } if swap { ipv4Layer.SrcIP, ipv4Layer.DstIP = ipv4Layer.DstIP, ipv4Layer.SrcIP } protoStack = append(protoStack, ipv4Layer) case TCP: tcpLayer := &layers.TCP{ SrcPort: layers.TCPPort(uint16(1024 + rnd.Intn(0x10000-1024))), DstPort: layers.TCPPort(uint16(1024 + rnd.Intn(0x10000-1024))), } if swap { tcpLayer.SrcPort, tcpLayer.DstPort = tcpLayer.DstPort, tcpLayer.SrcPort } protoStack = append(protoStack, tcpLayer) case UDP: udpLayer := &layers.UDP{ SrcPort: layers.UDPPort(uint16(1024 + rnd.Intn(0x10000-1024))), DstPort: layers.UDPPort(uint16(1024 + rnd.Intn(0x10000-1024))), } if swap { udpLayer.SrcPort, udpLayer.DstPort = udpLayer.DstPort, udpLayer.SrcPort } protoStack = append(protoStack, udpLayer) default: t.Log("forgeTestPacket : Unsupported protocol ", proto) } } protoStack = append(protoStack, gopacket.Payload(rawBytes)) buffer := gopacket.NewSerializeBuffer() options := gopacket.SerializeOptions{FixLengths: true} err := gopacket.SerializeLayers(buffer, options, protoStack...) if err != nil { t.Fail() } firstLayerType := layers.LayerTypeEthernet switch protos[0] { case IPv4: firstLayerType = layers.LayerTypeIPv4 case IPv6: firstLayerType = layers.LayerTypeIPv6 } gpacket := gopacket.NewPacket(buffer.Bytes(), firstLayerType, gopacket.Default) return &gpacket }
func (vnet *VNET) handleUDPForward(pkt *Packet, now time.Time) { defer pkt.Release() // fmt.Printf("UDP: %08x %s\n", pkt.Flags, pkt.String()) var err error if bytes.Equal(pkt.Eth.DstMAC, layers.EthernetBroadcast[:]) { // ignore return } if pkt.DstHost == nil { // ignore return } if !pkt.DstHost.Up { log.Printf("destination is down: %s", pkt.DstHost.Name) // ignore return } var ( srcIP net.IP dstIP net.IP srcPort = uint16(pkt.UDP.SrcPort) dstPort = uint16(pkt.UDP.DstPort) ) if pkt.IPv4 != nil { srcIP = CloneIP(pkt.IPv4.SrcIP.To16()) dstIP = CloneIP(pkt.IPv4.DstIP.To16()) } else if pkt.IPv6 != nil { srcIP = CloneIP(pkt.IPv6.SrcIP.To16()) dstIP = CloneIP(pkt.IPv6.DstIP.To16()) } else { log.Printf("invalid protocol") // ignore return } route := vnet.routes.GetTable().Lookup( protocols.UDP, srcIP, dstIP, srcPort, dstPort) if route == nil { rule, found := vnet.rules.GetTable().Lookup(protocols.UDP, pkt.DstHost.ID, dstPort) if !found { log.Printf("no rule") // ignore return } var ruleDstIP = rule.DstIP if ruleDstIP == nil { gateway := vnet.hosts.GetTable().LookupByName("gateway") if gateway == nil || !gateway.Up { log.Printf("no gateway") // ignore return } if dstIP.To4() != nil { if len(gateway.IPv4Addrs) > 0 { ruleDstIP = gateway.IPv4Addrs[0] } } else { if len(gateway.IPv6Addrs) > 0 { ruleDstIP = gateway.IPv6Addrs[0] } } } if ruleDstIP == nil { log.Printf("no destination ip") // ignore return } var r routes.Route r.Protocol = protocols.UDP r.HostID = pkt.DstHost.ID r.SetInboundSource(srcIP, srcPort) r.SetInboundDestination(dstIP, dstPort) r.SetOutboundDestination(ruleDstIP, rule.DstPort) route, err = vnet.routes.AddRoute(&r) if err != nil { // ignore log.Printf("UDP/error: %s", err) return } } if route == nil { log.Printf("no route") // ignore return } var ( eth layers.Ethernet udp layers.UDP ) eth = *pkt.Eth eth.SrcMAC, eth.DstMAC = eth.DstMAC, eth.SrcMAC udp = *pkt.UDP udp.SrcPort = layers.UDPPort(route.Outbound.SrcPort) udp.DstPort = layers.UDPPort(route.Outbound.DstPort) if route.Outbound.DstIP.To4() != nil { ip := layers.IPv4{ SrcIP: route.Outbound.SrcIP.To4(), DstIP: route.Outbound.DstIP.To4(), Version: 4, Protocol: layers.IPProtocolUDP, TTL: 64, } udp.SetNetworkLayerForChecksum(&ip) err = vnet.writePacket( ð, &ip, &udp, gopacket.Payload(pkt.UDP.Payload)) if err != nil { log.Printf("UDP/error: %s", err) return } } else { ip := layers.IPv6{ SrcIP: route.Outbound.SrcIP.To16(), DstIP: route.Outbound.DstIP.To16(), Version: 4, NextHeader: layers.IPProtocolUDP, } udp.SetNetworkLayerForChecksum(&ip) err = vnet.writePacket( ð, &ip, &udp, gopacket.Payload(pkt.UDP.Payload)) if err != nil { log.Printf("UDP/error: %s", err) return } } route.RoutedPacket(now, len(pkt.buf)) }
//Detectinitcwnd attempts to detect the initial congession window of an http endpoint. //First does a 3 way tcp handshake, sends GET request and then does not ack any response while measuring the packets received. This allows us to see how much data the server can send without acknowledgement. func Detectinitcwnd(host, url string, dstip net.IP) (pkt_count, payload_size int, fullpayload []byte, err error) { pldata := []byte(fmt.Sprintf("GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", url, host)) var dstport layers.TCPPort dstport = layers.TCPPort(80) srcip, sport := localIPPort(dstip) srcport := layers.TCPPort(sport) log.Printf("using srcip: %v", srcip.String()) log.Printf("using dstip: %v", dstip.String()) // Our IP header... not used, but necessary for TCP checksumming. ip := &layers.IPv4{ SrcIP: srcip, DstIP: dstip, Protocol: layers.IPProtocolTCP, } //layers.TCPOption{3, 3, []byte{7}} maybe for window scaling... dunno tcpopts := []layers.TCPOption{layers.TCPOption{2, 4, []byte{5, 172}}} //Set MSS 1452 // Our TCP header tcp := &layers.TCP{ SrcPort: srcport, DstPort: dstport, Seq: 1105024978, SYN: true, Window: 65535, Options: tcpopts, } tcp.SetNetworkLayerForChecksum(ip) // Serialize. Note: we only serialize the TCP layer, because the // socket we get with net.ListenPacket wraps our data in IPv4 packets // already. We do still need the IP layer to compute checksums // correctly, though. buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ ComputeChecksums: true, FixLengths: true, } err = gopacket.SerializeLayers(buf, opts, tcp) if err != nil { return } var out1 bytes.Buffer iptset := exec.Command("iptables", "-A", "OUTPUT", "-p", "tcp", "--tcp-flags", "RST", "RST", "-s", srcip.String(), "--sport", porttoint(srcport), "--dport", porttoint(dstport), "-j", "DROP") iptset.Stderr = &out1 log.Println(iptset) err = iptset.Run() if err != nil { return } log.Println(out1.String()) iptrem := exec.Command("iptables", "-D", "OUTPUT", "-p", "tcp", "--tcp-flags", "RST", "RST", "-s", srcip.String(), "--sport", porttoint(srcport), "--dport", porttoint(dstport), "-j", "DROP") conn, err := net.ListenPacket("ip4:tcp", "0.0.0.0") if err != nil { return } defer func() { fmt.Println(iptrem) var out bytes.Buffer iptrem.Stderr = &out err = iptrem.Run() if err != nil { log.Println(err) } fmt.Printf(out.String()) log.Println("Removed iptable rule") //Now RST should be allowed... send it rst_pkt := &layers.TCP{ SrcPort: srcport, DstPort: dstport, Seq: 1105024980, Window: 65535, RST: true, } rst_pkt.SetNetworkLayerForChecksum(ip) if err := gopacket.SerializeLayers(buf, opts, rst_pkt); err != nil { //Shadowing err since we dont care log.Println(err) } if _, err := conn.WriteTo(buf.Bytes(), &net.IPAddr{IP: dstip}); err != nil { //Shadowing err since we dont care log.Println(err) } }() log.Println("writing request") _, err = conn.WriteTo(buf.Bytes(), &net.IPAddr{IP: dstip}) if err != nil { return } // Set deadline so we don't wait forever. err = conn.SetDeadline(time.Now().Add(15 * time.Second)) if err != nil { return } //Capture synack from our syn, return the ack value ack, err := getack(conn, srcport, dstip.String()) if err != nil { log.Println(err) return } else { //Prepare http request, ack the synack payload := &layers.TCP{ SrcPort: srcport, DstPort: dstport, Seq: 1105024979, ACK: true, Window: 65535, Ack: ack + 1, } payload.SetNetworkLayerForChecksum(ip) if err := gopacket.SerializeLayers(buf, opts, payload, gopacket.Payload(pldata)); err != nil { log.Fatal(err) } if _, err := conn.WriteTo(buf.Bytes(), &net.IPAddr{IP: dstip}); err != nil { log.Fatal(err) } pkt_count, payload_size, fullpayload = listenandcount(conn, dstip.String(), srcport) log.Println("Initcwnd: ", pkt_count) log.Println("Data: ", payload_size) return } return }
func InjectPacket(pp *PacketParams, g *graph.Graph) error { srcdata := pp.SrcNode.Metadata() dstdata := pp.DstNode.Metadata() if _, ok := srcdata["IPV4"]; !ok { return errors.New("Source Node doesn't have an IP") } srcIP := getIP(srcdata["IPV4"].(string)) if srcIP == nil { return errors.New("Source Node doesn't have proper IP") } if _, ok := dstdata["IPV4"]; !ok { return errors.New("Destination Node doesn't have an IP") } dstIP := getIP(dstdata["IPV4"].(string)) if dstIP == nil { return errors.New("Destination Node doesn't have proper IP") } srcMAC, err := net.ParseMAC(srcdata["MAC"].(string)) if err != nil || srcMAC == nil { return errors.New("Source Node doesn't have proper MAC") } dstMAC, err := net.ParseMAC(dstdata["MAC"].(string)) if err != nil || dstMAC == nil { return errors.New("Destination Node doesn't have proper MAC") } //create packet buffer := gopacket.NewSerializeBuffer() ipLayer := &layers.IPv4{Version: 4, SrcIP: srcIP, DstIP: dstIP} ethLayer := &layers.Ethernet{EthernetType: layers.EthernetTypeIPv4, SrcMAC: srcMAC, DstMAC: dstMAC} switch pp.Type { case "icmp": ipLayer.Protocol = layers.IPProtocolICMPv4 gopacket.SerializeLayers(buffer, options, ethLayer, ipLayer, &layers.ICMPv4{ TypeCode: layers.CreateICMPv4TypeCode(layers.ICMPv4TypeEchoRequest, 0), }, gopacket.Payload([]byte(pp.Payload)), ) default: return fmt.Errorf("Unsupported traffic type '%s'", pp.Type) } g.RLock() srcNode := g.GetNode(pp.SrcNode.ID) if srcNode == nil { g.RUnlock() return errors.New("Unable to find source node") } nscontext, err := topology.NewNetNSContextByNode(g, srcNode) defer nscontext.Close() g.RUnlock() if err != nil { return err } handle, err := pcap.OpenLive(srcdata["Name"].(string), 1024, false, 2000) if err != nil { return fmt.Errorf("Unable to open the source node: %s", err.Error()) } defer handle.Close() packet := buffer.Bytes() for i := 0; i < pp.Count; i++ { if err := handle.WritePacketData(packet); err != nil { return fmt.Errorf("Write error: %s", err.Error()) } } return nil }
//sendPacket generates & sends a packet of arbitrary size to a specific destination. //The size specified should be larger then 40bytes. func sendPacket(sourceIP string, destinationIP string, size int, message string, appID int, chanID int, icmpType layers.ICMPv4TypeCode) []byte { var payloadSize int if size < 28 { //Unable to create smaller packets. payloadSize = 0 } else { payloadSize = size - 28 } //Convert IP to 4bit representation srcIP := net.ParseIP(sourceIP).To4() dstIP := net.ParseIP(destinationIP).To4() //IP Layer ip := layers.IPv4{ SrcIP: srcIP, DstIP: dstIP, Version: 4, TTL: 64, Protocol: layers.IPProtocolICMPv4, } icmp := layers.ICMPv4{ TypeCode: icmpType, } opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } ipHeaderBuf := gopacket.NewSerializeBuffer() err := ip.SerializeTo(ipHeaderBuf, opts) if err != nil { panic(err) } //Set "Don't Fragment"-Flag in Header ipHeader, err := ipv4.ParseHeader(ipHeaderBuf.Bytes()) ipHeader.Flags |= ipv4.DontFragment if err != nil { panic(err) } payloadBuf := gopacket.NewSerializeBuffer() //Influence the payload size payload := gopacket.Payload(generatePayload(payloadSize, ","+strconv.Itoa(appID)+","+strconv.Itoa(chanID)+","+message+",")) err = gopacket.SerializeLayers(payloadBuf, opts, &icmp, payload) if err != nil { panic(err) } //Send packet var packetConn net.PacketConn var rawConn *ipv4.RawConn packetConn, err = net.ListenPacket("ip4:icmp", srcIP.String()) if err != nil { panic(err) } rawConn, err = ipv4.NewRawConn(packetConn) if err != nil { panic(err) } err = rawConn.WriteTo(ipHeader, payloadBuf.Bytes(), nil) return append(ipHeaderBuf.Bytes(), payloadBuf.Bytes()...) }
func (vnet *VNET) handleDHCPOffer(pkt *Packet, offer *dhcp.Message) { if offer.YourIPAddress == nil { return } msg := &dhcp.Message{} msg.ClientMAC = vnet.system.ControllerMAC() msg.Type = dhcp.MessageTypeRequest msg.HardwareType = dhcp.MessageHardwareTypeEthernet msg.HardwareAddressLength = 6 msg.Hops = 0 msg.TransactionID = offer.TransactionID msg.Options = map[uint8]*dhcp.Option{ dhcp.OptionCodeDHCPMessageType: { Value: []byte{dhcp.DHCPMessageTypeRequest}, }, dhcp.OptionCodeDHCPClientidentifier: { Value: append([]byte{1}, msg.ClientMAC[:6]...), }, dhcp.OptionCodeDHCPRequestedIPAddress: { Value: offer.YourIPAddress.To4(), }, dhcp.OptionCodeDHCPServerIdentifier: offer.Options[dhcp.OptionCodeDHCPServerIdentifier], dhcp.OptionCodeDHCPMaximumMessageSize: { Value: []byte{2, 64}, // 576 }, dhcp.OptionCodeDHCPParameterRequestList: { Value: []byte{ dhcp.OptionCodeSubnetMask, dhcp.OptionCodeRouter, dhcp.OptionCodeDomainNameServer, dhcp.OptionCodeHostName, dhcp.OptionCodeDomainName, dhcp.OptionCodeBroadcastAddress, dhcp.OptionCodeNetworkTimeProtocolServers, }, }, dhcp.OptionCodeDHCPVendorclassidentifier: { Value: []byte("swtchbrd 1.23.1"), }, dhcp.OptionCodeEnd: {}, } ipv4 := &layers.IPv4{ SrcIP: net.IPv4(0, 0, 0, 0), DstIP: net.IPv4(255, 255, 255, 255), Version: 4, Protocol: layers.IPProtocolUDP, TTL: 64, } udp := &layers.UDP{ SrcPort: layers.UDPPort(68), DstPort: layers.UDPPort(67), } udp.SetNetworkLayerForChecksum(ipv4) err := vnet.writePacket( &layers.Ethernet{ SrcMAC: msg.ClientMAC, DstMAC: layers.EthernetBroadcast, EthernetType: layers.EthernetTypeIPv4, }, ipv4, udp, gopacket.Payload(writeDHCPMessage(msg))) if err != nil { log.Printf("DCHP/error: %s", err) return } return }
func main() { defer util.Run()() var handle *pcap.Handle var err error if *fname != "" { if handle, err = pcap.OpenOffline(*fname); err != nil { log.Fatal("PCAP OpenOffline error:", err) } } else { // This is a little complicated because we want to allow all possible options // for creating the packet capture handle... instead of all this you can // just call pcap.OpenLive if you want a simple handle. inactive, err := pcap.NewInactiveHandle(*iface) if err != nil { log.Fatal("could not create: %v", err) } defer inactive.CleanUp() if err = inactive.SetSnapLen(*snaplen); err != nil { log.Fatal("could not set snap length: %v", err) } else if err = inactive.SetPromisc(*promisc); err != nil { log.Fatal("could not set promisc mode: %v", err) } else if err = inactive.SetTimeout(time.Second); err != nil { log.Fatal("could not set timeout: %v", err) } if *tstype != "" { if t, err := pcap.TimestampSourceFromString(*tstype); err != nil { log.Fatalf("Supported timestamp types: %v", inactive.SupportedTimestamps()) } else if err := inactive.SetTimestampSource(t); err != nil { log.Fatalf("Supported timestamp types: %v", inactive.SupportedTimestamps()) } } inactive.SetImmediateMode(true) if handle, err = inactive.Activate(); err != nil { log.Fatal("PCAP Activate error:", err) } defer handle.Close() if len(flag.Args()) > 0 { bpffilter := strings.Join(flag.Args(), " ") fmt.Fprintf(os.Stderr, "Using BPF filter %q\n", bpffilter) if err = handle.SetBPFFilter(bpffilter); err != nil { log.Fatal("BPF filter error:", err) } } } packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for packet := range packetSource.Packets() { if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil { if tcpLayer.(*layers.TCP).DstPort != 80 { continue } if tcpLayer.(*layers.TCP).SYN || tcpLayer.(*layers.TCP).RST { continue } data := string(tcpLayer.(*layers.TCP).LayerPayload()) if !strings.HasPrefix(data, "GET") { continue } fmt.Println("I got GET packet!") ethLayer := packet.Layer(layers.LayerTypeEthernet) eth := layers.Ethernet{ SrcMAC: ethLayer.(*layers.Ethernet).DstMAC, DstMAC: ethLayer.(*layers.Ethernet).SrcMAC, EthernetType: layers.EthernetTypeIPv4, } ipv4Layer := packet.Layer(layers.LayerTypeIPv4) ipv4 := layers.IPv4{ Version: ipv4Layer.(*layers.IPv4).Version, SrcIP: ipv4Layer.(*layers.IPv4).DstIP, DstIP: ipv4Layer.(*layers.IPv4).SrcIP, TTL: 77, Id: ipv4Layer.(*layers.IPv4).Id, Protocol: layers.IPProtocolTCP, } tcp := layers.TCP{ SrcPort: tcpLayer.(*layers.TCP).DstPort, DstPort: tcpLayer.(*layers.TCP).SrcPort, PSH: true, ACK: true, FIN: true, Seq: tcpLayer.(*layers.TCP).Ack, Ack: tcpLayer.(*layers.TCP).Seq + uint32(len(data)), Window: 0, } tcp.SetNetworkLayerForChecksum(&ipv4) data = `HTTP/1.1 200 OK Server: nginx Date: Tue, 26 Jan 2016 13:09:19 GMT Content-Type: text/plain;charset=UTF-8 Connection: keep-alive Vary: Accept-Encoding Cache-Control: no-store Pragrma: no-cache Expires: Thu, 01 Jan 1970 00:00:00 GMT Cache-Control: no-cache Content-Length: 7 Stupid!` // Set up buffer and options for serialization. buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } if err := gopacket.SerializeLayers(buf, opts, ð, &ipv4, &tcp, gopacket.Payload([]byte(data))); err != nil { fmt.Println(err) } if err := handle.WritePacketData(buf.Bytes()); err != nil { fmt.Println(err) } fmt.Println("I sent Response-hijack packet!") } } // dumpcommand.Run(handle) }
// Given an EvePacket, convert the payload to a PCAP faking out the // headers as best we can. // // A buffer containing the 1 packet pcap file will be returned. func EvePayloadToPcap(event *EveEvent) ([]byte, error) { buffer := gopacket.NewSerializeBuffer() options := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } payloadLayer := gopacket.Payload(event.Payload.Bytes()) payloadLayer.SerializeTo(buffer, options) srcIp := net.ParseIP(event.SrcIP) if srcIp == nil { return nil, fmt.Errorf("Failed to parse IP address %s.", event.SrcIP) } dstIp := net.ParseIP(event.DstIP) if dstIp == nil { return nil, fmt.Errorf("Failed to parse IP address %s.", event.DstIP) } proto, err := ProtoNumber(event.Proto) if err != nil { return nil, err } switch proto { case layers.IPProtocolTCP: // Could probably fake up a better TCP layer here. tcpLayer := layers.TCP{ SrcPort: layers.TCPPort(event.SrcPort), DstPort: layers.TCPPort(event.DstPort), } tcpLayer.SerializeTo(buffer, options) break case layers.IPProtocolUDP: udpLayer := layers.UDP{ SrcPort: layers.UDPPort(event.SrcPort), DstPort: layers.UDPPort(event.DstPort), } udpLayer.SerializeTo(buffer, options) break case layers.IPProtocolICMPv4: icmpLayer := layers.ICMPv4{ TypeCode: layers.CreateICMPv4TypeCode( event.IcmpType, event.IcmpCode), Id: 0, Seq: 0, } icmpLayer.SerializeTo(buffer, options) break case layers.IPProtocolICMPv6: icmp6Layer := layers.ICMPv6{ TypeCode: layers.CreateICMPv6TypeCode( event.IcmpType, event.IcmpCode), } icmp6Layer.SerializeTo(buffer, options) break default: return nil, fmt.Errorf("Unsupported protocol %d.", proto) } isIp6 := dstIp.To4() == nil if !isIp6 { ipLayer := layers.IPv4{ SrcIP: srcIp, DstIP: dstIp, Version: 4, Protocol: proto, TTL: 64, } ipLayer.SerializeTo(buffer, options) } else { ip6Layer := layers.IPv6{ Version: 6, SrcIP: srcIp, DstIP: dstIp, } ip6Layer.SerializeTo(buffer, options) } return pcap.CreatePcap(event.Timestamp.Time, buffer.Bytes(), layers.LinkTypeRaw) }