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 }
func (p *GoPacketProbe) run(g *graph.Graph, n *graph.Node, capture *api.Capture) error { atomic.StoreInt64(&p.state, common.RunningState) g.RLock() ifName := n.Metadata()["Name"].(string) firstLayerType := getGoPacketFirstLayerType(n) nscontext, err := topology.NewNetNSContextByNode(g, n) g.RUnlock() defer nscontext.Close() if err != nil { return err } switch capture.Type { case "pcap": handle, err := pcap.OpenLive(ifName, snaplen, true, time.Second) if err != nil { return fmt.Errorf("Error while opening device %s: %s", ifName, err.Error()) } if err := handle.SetBPFFilter(capture.BPFFilter); err != nil { return fmt.Errorf("BPF Filter failed: %s", err) } p.handle = handle p.packetSource = gopacket.NewPacketSource(handle, handle.LinkType()) logging.GetLogger().Infof("PCAP Capture started on %s with First layer: %s", ifName, firstLayerType) default: var handle *AFPacketHandle fnc := func() error { handle, err = NewAFPacketHandle(ifName, snaplen) if err != nil { return fmt.Errorf("Error while opening device %s: %s", ifName, err.Error()) } return nil } if err = common.Retry(fnc, 2, 100*time.Millisecond); err != nil { return err } p.handle = handle p.packetSource = gopacket.NewPacketSource(handle, firstLayerType) logging.GetLogger().Infof("AfPacket Capture started on %s with First layer: %s", ifName, firstLayerType) } // leave the namespace, stay lock in the current thread nscontext.Quit() packetsChan := p.flowTable.Start() defer p.flowTable.Stop() p.feedFlowTable(packetsChan) return nil }