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 }
// 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) }