func main() { flag.Usage = usage flag.Parse() pcapfile, err := openPcap() if err != nil { glog.Fatalf("%v", err) } bpf := strings.Join(flag.Args(), " ") if err = pcapfile.SetBPFFilter(bpf); err != nil { glog.Fatalf("unable to set BPF: %v", err) } // "Pass this stream factory to an tcpassembly.StreamPool , // start up an tcpassembly.Assembler, and you're good to go!" done := make(chan struct{}) results := make(chan string) go printResults(done, results) wg := &sync.WaitGroup{} rtmp := &rtmpStreamWrapper{wg, results} pool := tcpassembly.NewStreamPool(rtmp) asm := tcpassembly.NewAssembler(pool) asm.MaxBufferedPagesTotal = 4096 // limit gopacket memory allocation source := gopacket.NewPacketSource(pcapfile, pcapfile.LinkType()) var pkt gopacket.Packet for { pkt, err = source.NextPacket() if pkt == nil || err != nil { break } if tcp := pkt.Layer(layers.LayerTypeTCP); tcp != nil { asm.AssembleWithTimestamp( pkt.TransportLayer().TransportFlow(), tcp.(*layers.TCP), pkt.Metadata().Timestamp) } } if err != nil && !errIsEOF(err) { glog.Errorf("packet: %v", err) if err = pcapfile.Error(); err != nil { glog.Errorf("pcap: %v", err) } } asm.FlushAll() // abort any in progress tcp connections wg.Wait() // tcp streams have finished processing close(results) // no more results will be generated by tcp streams <-done // printResults has finished }
func (f *fragmentList) insert(in gopacket.Packet) (gopacket.Packet, error) { // TODO: should keep a copy of *in in the list // or not (ie the packet source is reliable) ? fragv6 := in.Layer(layers.LayerTypeIPv6Fragment).(*layers.IPv6Fragment) fragOffset := fragv6.FragmentOffset * 8 if fragOffset >= f.Highest { f.List.PushBack(in) } else { for e := f.List.Front(); e != nil; e = e.Next() { packet, _ := e.Value.(gopacket.Packet) frag := packet.Layer(layers.LayerTypeIPv6Fragment).(*layers.IPv6Fragment) if fragv6.FragmentOffset <= frag.FragmentOffset { debug.Printf("defrag: inserting frag %d before existing frag %d \n", fragOffset, frag.FragmentOffset*8) f.List.InsertBefore(in, e) break } } } // packet.Metadata().Timestamp should have been better, but // we don't have this info there... f.LastSeen = in.Metadata().Timestamp fragLength := in.Layer(layers.LayerTypeIPv6).(*layers.IPv6).Length - 8 // need to conform // After inserting the Fragment, we update the counters if f.Highest < fragOffset+fragLength { f.Highest = fragOffset + fragLength } f.Current = f.Current + fragLength debug.Printf("defrag: insert ListLen: %d Highest:%d Current:%d\n", f.List.Len(), f.Highest, f.Current) // Final Fragment ? if fragv6.MoreFragments == false { f.FinalReceived = true } // Ready to try defrag ? if f.FinalReceived && f.Highest == f.Current { return f.build(in) } return nil, nil }
func GetPacketTime(packet gopacket.Packet) time.Time { return packet.Metadata().CaptureInfo.Timestamp }
// Handle reads the pcap file into assembled packets for the streamHandler func (p *PacketHandler) Handle(streamHandler StreamHandler, numToHandle int) error { count := int64(0) start := time.Now() if p.Verbose && numToHandle > 0 { userInfoLogger.Logvf(Always, "Processing", numToHandle, "packets") } source := gopacket.NewPacketSource(p.pcap, p.pcap.LinkType()) streamPool := NewStreamPool(streamHandler) assembler := NewAssembler(streamPool) defer func() { if userInfoLogger.isInVerbosity(DebugLow) { userInfoLogger.Logv(DebugLow, "flushing assembler.") userInfoLogger.Logvf(DebugLow, "num flushed/closed: %v", assembler.FlushAll()) userInfoLogger.Logv(DebugLow, "closing stream handler.") } else { assembler.FlushAll() } streamHandler.Close() }() defer func() { if userInfoLogger.isInVerbosity(DebugLow) { userInfoLogger.Logvf(DebugLow, "Dropped %v packets out of %v", p.numDropped, count) runTime := float64(time.Now().Sub(start)) / float64(time.Second) userInfoLogger.Logvf(DebugLow, "Processed %v packets per second", float64(count-p.numDropped)/runTime) } }() ticker := time.Tick(time.Second * 1) var pkt gopacket.Packet var pktCount uint for { select { case pkt = <-source.Packets(): pktCount++ if pkt == nil { // end of pcap file userInfoLogger.Logv(DebugLow, "Reached end of stream") return nil } if tcpLayer := pkt.Layer(layers.LayerTypeTCP); tcpLayer != nil { userInfoLogger.Logv(DebugHigh, "Assembling TCP layer") assembler.AssembleWithTimestamp( pkt.TransportLayer().TransportFlow(), tcpLayer.(*layers.TCP), pkt.Metadata().Timestamp) // TODO: use time.Now() here when running in realtime mode } if count == 0 { if firstSeener, ok := streamHandler.(SetFirstSeener); ok { firstSeener.SetFirstSeen(pkt.Metadata().Timestamp) } } count++ if numToHandle > 0 && count >= int64(numToHandle) { userInfoLogger.Logv(DebugLow, "Count exceeds requested packets, returning.") break } select { case <-ticker: bookkeep(pktCount, pkt, assembler) default: } case <-ticker: bookkeep(pktCount, pkt, assembler) case <-p.stop: return nil } } }
func bookkeep(pktCount uint, pkt gopacket.Packet, assembler *Assembler) { if pkt != nil { userInfoLogger.Logvf(DebugLow, "processed packet %7.v with timestamp %v", pktCount, pkt.Metadata().Timestamp.Format(time.RFC3339)) assembler.FlushOlderThan(pkt.Metadata().CaptureInfo.Timestamp.Add(time.Minute * -5)) } }