Ejemplo n.º 1
0
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
}
Ejemplo n.º 2
0
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
}
Ejemplo n.º 3
0
func GetPacketTime(packet gopacket.Packet) time.Time {
	return packet.Metadata().CaptureInfo.Timestamp
}
Ejemplo n.º 4
0
// 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
		}
	}
}
Ejemplo n.º 5
0
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))
	}
}