@@ -6,17 +6,18 @@ import (
66 "io"
77 "net"
88 "os"
9- "path/filepath"
109 "time"
1110
1211 "github.com/mdlayher/packet"
1312 "github.com/packetcap/go-pcap/filter"
14- "github.com/shadowy-pycoder/mshark/mpcap"
15- "github.com/shadowy-pycoder/mshark/mpcapng"
1613 "golang.org/x/net/bpf"
1714 "golang.org/x/sys/unix"
1815)
1916
17+ type PacketWriter interface {
18+ WritePacket (timestamp time.Time , data []byte ) error
19+ }
20+
2021type layers struct {
2122 ether EthernetFrame
2223 ip IPv4Packet
@@ -29,39 +30,31 @@ type layers struct {
2930}
3031
3132type Config struct {
32- Iface string // The name of the network interface ("any" means listen on all interfaces).
33- Snaplen int // The maximum length of each packet snapshot.
34- Promisc bool // Promiscuous mode. This setting is ignored for "any" interface.
35- Timeout time.Duration // The maximum duration of the packet capture process.
36- PacketCount int // The maximum number of packets to capture.
37- Expr string // BPF filter expression.
38- File io.Writer // File to write captured packet data to.
39- Pcap bool // Create a PCAP file in the current working directory.
40- PcapNG bool // Create a PCAPNG file in the current working directory.
33+ Device * net.Interface // The name of the network interface ("any" means listen on all interfaces).
34+ Snaplen int // The maximum length of each packet snapshot.
35+ Promisc bool // Promiscuous mode. This setting is ignored for "any" interface.
36+ Timeout time.Duration // The maximum duration of the packet capture process.
37+ PacketCount int // The maximum number of packets to capture.
38+ Expr string // BPF filter expression.
4139}
4240
4341type Writer struct {
44- w io.Writer
45- layers layers
46- packetNum uint64
42+ w io.Writer
43+ layers layers
44+ packets uint64
4745}
4846
4947// NewWriter creates a new mshark Writer.
50- //
51- // If the io.Writer is nil, the Writer will write to stdout.
5248func NewWriter (w io.Writer ) * Writer {
53- if w == nil {
54- w = os .Stdout
55- }
5649 return & Writer {w : w }
5750}
5851
5952// WritePacket writes a packet to the writer, along with its timestamp.
6053//
6154// Timestamps are to be generated by the calling code.
6255func (mw * Writer ) WritePacket (timestamp time.Time , data []byte ) error {
63- mw .packetNum ++
64- fmt .Fprintf (mw .w , "- Packet: %d Timestamp: %s\n " , mw .packetNum , timestamp .Format ("2006-01-02T15:04:05-0700" ))
56+ mw .packets ++
57+ fmt .Fprintf (mw .w , "- Packet: %d Timestamp: %s\n " , mw .packets , timestamp .Format ("2006-01-02T15:04:05-0700" ))
6558 fmt .Fprintln (mw .w , "==================================================================" )
6659 if err := mw .layers .ether .Parse (data ); err != nil {
6760 return err
@@ -134,7 +127,7 @@ func (mw *Writer) WritePacket(timestamp time.Time, data []byte) error {
134127// - Timeout: 5s
135128// - Number of Packets: 0
136129// - BPF Filter: "ip proto tcp"
137- func (mw * Writer ) WriteHeader (c * Config , in * net. Interface , snaplen int ) error {
130+ func (mw * Writer ) WriteHeader (c * Config ) error {
138131 _ , err := fmt .Fprintf (mw .w , `- Interface: %s
139132- Snapshot Length: %d
140133- Promiscuous Mode: %v
@@ -143,9 +136,9 @@ func (mw *Writer) WriteHeader(c *Config, in *net.Interface, snaplen int) error {
143136- BPF Filter: %q
144137
145138` ,
146- in .Name ,
147- snaplen ,
148- in .Name != "any" && c .Promisc ,
139+ c . Device .Name ,
140+ c . Snaplen ,
141+ c . Device .Name != "any" && c .Promisc ,
149142 c .Timeout ,
150143 c .PacketCount ,
151144 c .Expr ,
@@ -178,7 +171,7 @@ func InterfaceByName(name string) (*net.Interface, error) {
178171 return in , nil
179172}
180173
181- func OpenLive (conf * Config ) error {
174+ func OpenLive (conf * Config , pw PacketWriter ) error {
182175
183176 packetcfg := packet.Config {}
184177
@@ -197,14 +190,8 @@ func OpenLive(conf *Config) error {
197190 packetcfg .Filter = raw
198191 }
199192
200- // getting interface
201- in , err := InterfaceByName (conf .Iface )
202- if err != nil {
203- return err
204- }
205-
206193 // opening connection
207- c , err := packet .Listen (in , packet .Raw , unix .ETH_P_ALL , & packetcfg )
194+ c , err := packet .Listen (conf . Device , packet .Raw , unix .ETH_P_ALL , & packetcfg )
208195 if err != nil {
209196 if errors .Is (err , os .ErrPermission ) {
210197 return fmt .Errorf ("permission denied (try setting CAP_NET_RAW capability): %v" , err )
@@ -213,7 +200,7 @@ func OpenLive(conf *Config) error {
213200 }
214201
215202 // setting promisc mode
216- if in .Name != "any" {
203+ if conf . Device .Name != "any" {
217204 if err := c .SetPromiscuous (conf .Promisc ); err != nil {
218205 return fmt .Errorf ("unable to set promiscuous mode: %v" , err )
219206 }
@@ -225,56 +212,17 @@ func OpenLive(conf *Config) error {
225212 return fmt .Errorf ("unable to set timeout: %v" , err )
226213 }
227214 }
228- // snaplen
229- snaplen := conf .Snaplen
230- if snaplen <= 0 || snaplen > 65535 {
231- snaplen = 65535
232- }
233- b := make ([]byte , snaplen )
234-
235- // file to write packets
236- f := NewWriter (conf .File )
237- if err := f .WriteHeader (conf , in , snaplen ); err != nil {
238- return err
239- }
240-
241- // pcap file to write packets
242- var pcap * mpcap.Writer
243- if conf .Pcap {
244- path := fmt .Sprintf ("./mshark_%s.pcap" , time .Now ().UTC ().Format ("20060102_150405" ))
245- fpcap , err := os .OpenFile (filepath .FromSlash (path ), os .O_CREATE | os .O_WRONLY , 0644 )
246- if err != nil {
247- return fmt .Errorf ("failed to open file: %v" , err )
248- }
249- defer fpcap .Close ()
250- pcap = mpcap .NewWriter (fpcap )
251- if err := pcap .WriteHeader (snaplen ); err != nil {
252- return err
253- }
254- }
255-
256- // pcapng file to write packets
257- var pcapng * mpcapng.Writer
258- if conf .PcapNG {
259- path := fmt .Sprintf ("./mshark_%s.pcapng" , time .Now ().UTC ().Format ("20060102_150405" ))
260- fpcapng , err := os .OpenFile (filepath .FromSlash (path ), os .O_CREATE | os .O_WRONLY , 0644 )
261- if err != nil {
262- return fmt .Errorf ("failed to open file: %v" , err )
263- }
264- defer fpcapng .Close ()
265- pcapng = mpcapng .NewWriter (fpcapng )
266- if err := pcapng .WriteHeader ("mshark" , in , conf .Expr , snaplen ); err != nil {
267- return err
268- }
269- }
270215
271216 defer func () {
272217 stats , err := c .Stats ()
273218 if err != nil {
274219 fmt .Fprintf (os .Stderr , "failed to fetch stats: %v" , err )
275220 } else {
276- fmt .Fprintf (f .w , "- Packets: %d, Drops: %d, Freeze Queue Count: %d\n - Packets Captured: %d\n " ,
277- stats .Packets , stats .Drops , stats .FreezeQueueCount , f .packetNum )
221+ fmt .Printf ("- Packets: %d, Drops: %d, Freeze Queue Count: %d\n " ,
222+ stats .Packets , stats .Drops , stats .FreezeQueueCount )
223+ if w , ok := pw .(* Writer ); ok {
224+ fmt .Printf ("- Packets Captured: %d\n " , w .packets )
225+ }
278226 }
279227 // close Conn
280228 c .Close ()
@@ -287,6 +235,8 @@ func OpenLive(conf *Config) error {
287235 }
288236 infinity := count == 0
289237
238+ b := make ([]byte , conf .Snaplen )
239+
290240 for i := 0 ; infinity || i < count ; i ++ {
291241 n , _ , err := c .ReadFrom (b )
292242 if err != nil {
@@ -296,22 +246,7 @@ func OpenLive(conf *Config) error {
296246 return fmt .Errorf ("failed to read Ethernet frame: %v" , err )
297247 }
298248
299- timestamp := time .Now ().UTC ()
300- data := b [:n ]
301-
302- if conf .Pcap {
303- if err := pcap .WritePacket (timestamp , data ); err != nil {
304- return err
305- }
306- }
307-
308- if conf .PcapNG {
309- if err := pcapng .WritePacket (timestamp , data ); err != nil {
310- return err
311- }
312- }
313-
314- if err := f .WritePacket (timestamp , data ); err != nil {
249+ if err := pw .WritePacket (time .Now ().UTC (), b [:n ]); err != nil {
315250 return err
316251 }
317252 }
0 commit comments