// readARP watches a handle for incoming ARP responses we might care about, and prints them. // // readARP loops until 'stop' is closed. func readARP(handle *pcap.Handle, iface *net.Interface, stop chan struct{}) { src := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet) in := src.Packets() for { var packet gopacket.Packet select { case <-stop: return case packet = <-in: arpLayer := packet.Layer(layers.LayerTypeARP) if arpLayer == nil { continue } arp := arpLayer.(*layers.ARP) if arp.Operation != layers.ARPReply || bytes.Equal([]byte(iface.HardwareAddr), arp.SourceHwAddress) { // This is a packet I sent. continue } // Note: we might get some packets here that aren't responses to ones we've sent, // if for example someone else sends US an ARP request. Doesn't much matter, though... // all information is good information :) log.Printf("IP %v is at %v", net.IP(arp.SourceProtAddress), net.HardwareAddr(arp.SourceHwAddress)) } } }
func TestPcapFileRead(t *testing.T) { for _, file := range []struct { filename string num int expectedLayers []gopacket.LayerType }{ {"test_loopback.pcap", 24, []gopacket.LayerType{ layers.LayerTypeLoopback, layers.LayerTypeIPv6, layers.LayerTypeTCP, }, }, {"test_ethernet.pcap", 16, []gopacket.LayerType{ layers.LayerTypeEthernet, layers.LayerTypeIPv4, layers.LayerTypeTCP, }, }, {"test_dns.pcap", 10, []gopacket.LayerType{ layers.LayerTypeEthernet, layers.LayerTypeIPv4, layers.LayerTypeUDP, layers.LayerTypeDNS, }, }, } { t.Logf("\n\n\n\nProcessing file %s\n\n\n\n", file.filename) packets := []gopacket.Packet{} if handle, err := OpenOffline(file.filename); err != nil { t.Fatal(err) } else { packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for packet := range packetSource.Packets() { packets = append(packets, packet) } } if len(packets) != file.num { t.Fatal("Incorrect number of packets, want", file.num, "got", len(packets)) } for i, p := range packets { t.Log(p.Dump()) for _, layertype := range file.expectedLayers { if p.Layer(layertype) == nil { t.Fatal("Packet", i, "has no layer type\n%s", layertype, p.Dump()) } } } } }
func Run(src gopacket.PacketDataSource) { if !flag.Parsed() { log.Fatalln("Run called without flags.Parse() being called") } var dec gopacket.Decoder var ok bool if dec, ok = gopacket.DecodersByLayerName[*decoder]; !ok { log.Fatalln("No decoder named", *decoder) } source := gopacket.NewPacketSource(src, dec) source.Lazy = *lazy source.NoCopy = true fmt.Fprintln(os.Stderr, "Starting to read packets") count := 0 bytes := int64(0) start := time.Now() errors := 0 truncated := 0 layertypes := map[gopacket.LayerType]int{} for packet := range source.Packets() { count++ bytes += int64(len(packet.Data())) if *dump { fmt.Println(packet.Dump()) } else if *print { fmt.Println(packet) } if !*lazy || *print || *dump { // if we've already decoded all layers... for _, layer := range packet.Layers() { layertypes[layer.LayerType()]++ } if packet.Metadata().Truncated { truncated++ } if errLayer := packet.ErrorLayer(); errLayer != nil { errors++ if *printErrors { fmt.Println("Error:", errLayer.Error()) fmt.Println("--- Packet ---") fmt.Println(packet.Dump()) } } } done := *maxcount > 0 && count >= *maxcount if count%*statsevery == 0 || done { fmt.Fprintf(os.Stderr, "Processed %v packets (%v bytes) in %v, %v errors and %v truncated packets\n", count, bytes, time.Since(start), errors, truncated) if len(layertypes) > 0 { fmt.Fprintf(os.Stderr, "Layer types seen: %+v\n", layertypes) } } if done { break } } }
func main() { defer util.Run()() var handle *pcap.Handle var err error // Set up pcap packet capture if *fname != "" { log.Printf("Reading from pcap dump %q", *fname) handle, err = pcap.OpenOffline(*fname) } else { log.Printf("Starting capture on interface %q", *iface) handle, err = pcap.OpenLive(*iface, int32(*snaplen), true, pcap.BlockForever) } if err != nil { log.Fatal(err) } if err := handle.SetBPFFilter(*filter); err != nil { log.Fatal(err) } // Set up assembly streamFactory := &httpStreamFactory{} streamPool := tcpassembly.NewStreamPool(streamFactory) assembler := tcpassembly.NewAssembler(streamPool) log.Println("reading in packets") // Read in packets, pass to assembler. packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) packets := packetSource.Packets() ticker := time.Tick(time.Minute) for { select { case packet := <-packets: // A nil packet indicates the end of a pcap file. if packet == nil { return } if *logAllPackets { log.Println(packet) } if packet.NetworkLayer() == nil || packet.TransportLayer() == nil || packet.TransportLayer().LayerType() != layers.LayerTypeTCP { log.Println("Unusable packet") continue } tcp := packet.TransportLayer().(*layers.TCP) assembler.AssembleWithTimestamp(packet.NetworkLayer().NetworkFlow(), tcp, packet.Metadata().Timestamp) case <-ticker: // Every minute, flush connections that haven't seen activity in the past 2 minutes. assembler.FlushOlderThan(time.Now().Add(time.Minute * -2)) } } }
func main() { defer util.Run()() log.Printf("starting capture on interface %q", *iface) // Set up pcap packet capture handle, err := pcap.OpenLive(*iface, int32(*snaplen), true, pcap.BlockForever) if err != nil { panic(err) } if err := handle.SetBPFFilter(*filter); err != nil { panic(err) } // Set up assembly streamFactory := &myFactory{bidiMap: make(map[key]*bidi)} streamPool := tcpassembly.NewStreamPool(streamFactory) assembler := tcpassembly.NewAssembler(streamPool) log.Println("reading in packets") // Read in packets, pass to assembler. packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) packets := packetSource.Packets() ticker := time.Tick(timeout / 4) for { select { case packet := <-packets: if *logAllPackets { log.Println(packet) } if packet.NetworkLayer() == nil || packet.TransportLayer() == nil || packet.TransportLayer().LayerType() != layers.LayerTypeTCP { log.Println("Unusable packet") continue } tcp := packet.TransportLayer().(*layers.TCP) assembler.AssembleWithTimestamp(packet.NetworkLayer().NetworkFlow(), tcp, packet.Metadata().Timestamp) case <-ticker: // Every minute, flush connections that haven't seen activity in the past minute. log.Println("---- FLUSHING ----") assembler.FlushOlderThan(time.Now().Add(-timeout)) streamFactory.collectOldStreams() } } }
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 } fmt.Println() for i := 0; i < *repeat; i++ { packetDataSource.Reset() fmt.Printf("Benchmarking decode %d/%d\n", i+1, *repeat) benchmarkPacketDecode(packetSource) } fmt.Println() for i := 0; i < *repeat; i++ { packetDataSource.Reset() fmt.Printf("Benchmarking decoding layer parser %d/%d\n", i+1, *repeat) benchmarkLayerDecode(packetDataSource, false) } fmt.Println() for i := 0; i < *repeat; i++ { packetDataSource.Reset() fmt.Printf("Benchmarking decoding layer parser with assembly %d/%d\n", i+1, *repeat) benchmarkLayerDecode(packetDataSource, true) } }