github.com/gopacket/gopacket@v1.1.0/dumpcommand/tcpdump.go (about) 1 // Copyright 2012 Google, Inc. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style license 4 // that can be found in the LICENSE file in the root of the source 5 // tree. 6 7 // Package dumpcommand implements a run function for pfdump and pcapdump 8 // with many similar flags/features to tcpdump. This code is split out seperate 9 // from data sources (pcap/pfring) so it can be used by both. 10 package dumpcommand 11 12 import ( 13 "flag" 14 "fmt" 15 "log" 16 "os" 17 "time" 18 19 "github.com/gopacket/gopacket" 20 "github.com/gopacket/gopacket/ip4defrag" 21 "github.com/gopacket/gopacket/layers" // pulls in all layers decoders 22 ) 23 24 var ( 25 print = flag.Bool("print", true, "Print out packets, if false only prints out statistics") 26 maxcount = flag.Int("c", -1, "Only grab this many packets, then exit") 27 decoder = flag.String("decoder", "Ethernet", "Name of the decoder to use") 28 dump = flag.Bool("X", false, "If true, dump very verbose info on each packet") 29 statsevery = flag.Int("stats", 1000, "Output statistics every N packets") 30 printErrors = flag.Bool("errors", false, "Print out packet dumps of decode errors, useful for checking decoders against live traffic") 31 lazy = flag.Bool("lazy", false, "If true, do lazy decoding") 32 defrag = flag.Bool("defrag", false, "If true, do IPv4 defrag") 33 ) 34 35 func Run(src gopacket.PacketDataSource) { 36 if !flag.Parsed() { 37 log.Fatalln("Run called without flags.Parse() being called") 38 } 39 var dec gopacket.Decoder 40 var ok bool 41 if dec, ok = gopacket.DecodersByLayerName[*decoder]; !ok { 42 log.Fatalln("No decoder named", *decoder) 43 } 44 source := gopacket.NewPacketSource(src, dec) 45 source.Lazy = *lazy 46 source.NoCopy = true 47 source.DecodeStreamsAsDatagrams = true 48 fmt.Fprintln(os.Stderr, "Starting to read packets") 49 count := 0 50 bytes := int64(0) 51 start := time.Now() 52 errors := 0 53 truncated := 0 54 layertypes := map[gopacket.LayerType]int{} 55 defragger := ip4defrag.NewIPv4Defragmenter() 56 57 for packet := range source.Packets() { 58 count++ 59 bytes += int64(len(packet.Data())) 60 61 // defrag the IPv4 packet if required 62 if *defrag { 63 ip4Layer := packet.Layer(layers.LayerTypeIPv4) 64 if ip4Layer == nil { 65 continue 66 } 67 ip4 := ip4Layer.(*layers.IPv4) 68 l := ip4.Length 69 70 newip4, err := defragger.DefragIPv4(ip4) 71 if err != nil { 72 log.Fatalln("Error while de-fragmenting", err) 73 } else if newip4 == nil { 74 continue // packet fragment, we don't have whole packet yet. 75 } 76 if newip4.Length != l { 77 fmt.Printf("Decoding re-assembled packet: %s\n", newip4.NextLayerType()) 78 pb, ok := packet.(gopacket.PacketBuilder) 79 if !ok { 80 panic("Not a PacketBuilder") 81 } 82 nextDecoder := newip4.NextLayerType() 83 nextDecoder.Decode(newip4.Payload, pb) 84 } 85 } 86 87 if *dump { 88 fmt.Println(packet.Dump()) 89 } else if *print { 90 fmt.Println(packet) 91 } 92 if !*lazy || *print || *dump { // if we've already decoded all layers... 93 for _, layer := range packet.Layers() { 94 layertypes[layer.LayerType()]++ 95 } 96 if packet.Metadata().Truncated { 97 truncated++ 98 } 99 if errLayer := packet.ErrorLayer(); errLayer != nil { 100 errors++ 101 if *printErrors { 102 fmt.Println("Error:", errLayer.Error()) 103 fmt.Println("--- Packet ---") 104 fmt.Println(packet.Dump()) 105 } 106 } 107 } 108 done := *maxcount > 0 && count >= *maxcount 109 if count%*statsevery == 0 || done { 110 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) 111 if len(layertypes) > 0 { 112 fmt.Fprintf(os.Stderr, "Layer types seen: %+v\n", layertypes) 113 } 114 } 115 if done { 116 break 117 } 118 } 119 }