예제 #1
0
func benchmarkPacketDecode(packetSource *gopacket.PacketSource) {
	count, errors := 0, 0
	start := time.Now()
	for packet, err := packetSource.NextPacket(); err != io.EOF; packet, err = packetSource.NextPacket() {
		if err != nil {
			fmt.Println("Error reading in packet:", err)
			continue
		}
		count++
		var hasError bool
		if *printErrors && packet.ErrorLayer() != nil {
			fmt.Println("\n\n\nError decoding packet:", packet.ErrorLayer().Error())
			fmt.Println(hex.Dump(packet.Data()))
			fmt.Printf("%#v\n", packet.Data())
			errors++
			hasError = true
		}
		if *printLayers || hasError {
			fmt.Printf("\n=== PACKET %d ===\n", count)
			for _, l := range packet.Layers() {
				fmt.Printf("--- LAYER %v ---\n%#v\n\n", l.LayerType(), l)
			}
			fmt.Println()
		}
	}
	duration := time.Since(start)
	fmt.Printf("\tRead in %v packets in %v, %v per packet\n", count, duration, duration/time.Duration(count))
	if *printErrors {
		fmt.Printf("%v errors, successfully decoded %.02f%%\n", errors, float64(count-errors)*100.0/float64(count))
	}
}
예제 #2
0
// Packet reading --------------------------------------------------------------------
func(g *GPCapture) ReadPackets(packetSource *gopacket.PacketSource) {

    var numConsecDecodingFailures int

    SysLog.Debug("Entered Read packets")

    for {
        select {
        case <-g.quitCaptureChan:
            return
        default:
            // repeatedly read the packets from the packet source, return an error string
            // if the packet could not be decoded
            if packet, packerr := packetSource.NextPacket(); packerr == nil {

                // safely increment packet counter
                atomic.AddUint64(&g.pktsRead, 1)

                // OSAG gopacket addition: make sure that non-standard encapsulated packets
                // are sliced up correctly. The original gopacket does not support GRE-en-
                // capsulated packets for example
                packet.StripHeaders(g.linkType)

                // pull out the flow-relevant information and write it to the flow matrix.
                // Block the write out thread for the time of the insertion
                if p, perr := g.handlePacket(packet); perr == nil {

                    // protect critical section
                    g.flowTab.Lock()
                    g.flowTab.flows.addToFlow(p)
                    g.flowTab.Unlock()

                    numConsecDecodingFailures = 0
                } else {
                   numConsecDecodingFailures++

                    // shut down the interface thread if too many consecutive decoding failures
                    // have been encountered
                    if numConsecDecodingFailures > 10000 {
                       SysLog.Err(g.iface+": the last 10 000 packets could not be decoded")
                       return
                    }
                }
            } else if packerr == pcap.NextErrorTimeoutExpired {
                continue
            } else {
                SysLog.Warning(g.iface+": interface capture error: " + packerr.Error())
                return
            }
        }
    }
}
예제 #3
0
func main() {
	flag.Parse()
	filename := os.TempDir() + string(os.PathSeparator) + "gopacket_benchmark.pcap"
	if _, err := os.Stat(filename); err != nil {
		// This URL points to a publicly available packet data set from a DARPA
		// intrusion detection evaluation.  See
		// http://www.ll.mit.edu/mission/communications/cyber/CSTcorpora/ideval/data/1999/training/week1/index.html
		// for more details.
		fmt.Println("Local pcap file", filename, "doesn't exist, reading from", *url)
		if resp, err := http.Get(*url); err != nil {
			panic(err)
		} else if out, err := os.Create(filename); err != nil {
			panic(err)
		} else if gz, err := gzip.NewReader(resp.Body); err != nil {
			panic(err)
		} else if n, err := io.Copy(out, gz); err != nil {
			panic(err)
		} else if err := gz.Close(); err != nil {
			panic(err)
		} else if err := out.Close(); err != nil {
			panic(err)
		} else {
			fmt.Println("Successfully read", n, "bytes from url, unzipped to local storage")
		}
	}
	fmt.Println("Reading file once through to hopefully cache most of it")
	if f, err := os.Open(filename); err != nil {
		panic(err)
	} else if n, err := io.Copy(ioutil.Discard, f); err != nil {
		panic(err)
	} else if err := f.Close(); err != nil {
		panic(err)
	} else {
		fmt.Println("Read in file", filename, ", total of", n, "bytes")
	}
	if *cpuProfile != "" {
		if cpu, err := os.Create(*cpuProfile); err != nil {
			panic(err)
		} else if err := pprof.StartCPUProfile(cpu); err != nil {
			panic(err)
		} else {
			defer func() {
				pprof.StopCPUProfile()
				cpu.Close()
			}()
		}
	}
	var packetDataSource *BufferPacketSource
	var packetSource *gopacket.PacketSource
	fmt.Printf("Opening file %q for read\n", filename)
	if h, err := pcap.OpenOffline(filename); err != nil {
		panic(err)
	} else {
		fmt.Println("Reading all packets into memory with BufferPacketSource.")
		start := time.Now()
		packetDataSource = NewBufferPacketSource(h)
		duration := time.Since(start)
		fmt.Printf("Time to read packet data into memory from file: %v\n", duration)
		packetSource = gopacket.NewPacketSource(packetDataSource, h.LinkType())
		packetSource.DecodeOptions.Lazy = *decodeLazy
		packetSource.DecodeOptions.NoCopy = *decodeNoCopy
	}
	for i := 0; i < *repeat; i++ {
		packetDataSource.Reset()
		count, errors := 0, 0
		runtime.GC()
		fmt.Printf("Benchmarking decode %d/%d\n", i+1, *repeat)
		start := time.Now()
		for packet, err := packetSource.NextPacket(); err != io.EOF; packet, err = packetSource.NextPacket() {
			if err != nil {
				fmt.Println("Error reading in packet:", err)
			}
			count++
			var hasError bool
			if *printErrors && packet.ErrorLayer() != nil {
				fmt.Println("\n\n\nError decoding packet:", packet.ErrorLayer().Error())
				fmt.Println(hex.Dump(packet.Data()))
				fmt.Printf("%#v\n", packet.Data())
				errors++
				hasError = true
			}
			if *printLayers || hasError {
				fmt.Printf("\n=== PACKET %d ===\n", count)
				for _, l := range packet.Layers() {
					fmt.Printf("--- LAYER %v ---\n%#v\n\n", l.LayerType(), l)
				}
				fmt.Println()
			}
		}
		duration := time.Since(start)
		fmt.Printf("\tRead in %v packets in %v, %v per packet\n", count, duration, duration/time.Duration(count))
		if *printErrors {
			fmt.Printf("%v errors, successfully decoded %.02f%%\n", errors, float64(count-errors)*100.0/float64(count))
		}
	}
}
예제 #4
0
// This function gets the interface and configuration parameters from the core process
// and starts handling packets that are captured with gopacket.pcap
func (g *GPCapture) CaptureInterface(snapLen int32, promiscMode bool, bpfFilterString string,
                                     threadTerminationChan chan string,
                                     iwg *sync.WaitGroup) {
    go func() {
        defer g.CaptureDefer(threadTerminationChan)

        var (
            err                       error
            packetSource              *gopacket.PacketSource
        )

        SysLog.Info(g.iface+": setting up capture")

        // loopback does not support in/out-bound filters, thus ignore it
        if g.iface == "lo" {
            SysLog.Err(g.iface+": interface not supported")
            iwg.Done()
            return
        }

        // open packet stream from an interface
        if g.pcapHandle, err = pcap.OpenLive(g.iface, snapLen, promiscMode, 250*time.Millisecond); err != nil {
            SysLog.Err(g.iface+": could not open capture: "+err.Error())
            iwg.Done()
            return
        }

        // set the BPF filter. This has to be done in order to ensure that the link
        // type is identified correctly
        if e := g.pcapHandle.SetBPFFilter(bpfFilterString); e != nil {
            SysLog.Err(g.iface+": error setting BPF filter: " + e.Error())
            iwg.Done()
            return
        }
        SysLog.Debug(g.iface+": bpf set")

        // return from function in case the link type is zero (which can happen if the
        // specified interface does not exist (anymore))
        if g.pcapHandle.LinkType() == layers.LinkTypeNull {
            SysLog.Err(g.iface+": link type is null")
            iwg.Done()
            return
        }

        SysLog.Debug(g.iface+": link type: "+g.pcapHandle.LinkType().String())

        // specify the pcap as the source from which the packets will be read
        packetSource = gopacket.NewPacketSource(g.pcapHandle, g.pcapHandle.LinkType())

        // set the decoding options to lazy decoding in order to ensure that the packet
        // layers are only decoded once they are needed. Additionally, this is imperative
        // when GRE-encapsulated packets are decoded because otherwise the layers cannot
        // be detected correctly. Additionally set the link type for this interface
        packetSource.DecodeOptions = gopacket.Lazy
        g.linkType                 = int(g.pcapHandle.LinkType())

        SysLog.Debug(g.iface+": set packet source")

        iwg.Done()

        // perform the actual packet capturing:
        g.ReadPackets(packetSource)

    }()

}