Skip to content

Commit bcf30ce

Browse files
author
shadowy-pycoder
committed
Added support for multiple PacketWriters
1 parent 0847b9e commit bcf30ce

File tree

2 files changed

+79
-49
lines changed

2 files changed

+79
-49
lines changed

cmd/mshark/cli.go

Lines changed: 68 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"net"
77
"os"
88
"path/filepath"
9+
"slices"
910
"strings"
1011
"text/tabwriter"
1112
"time"
@@ -35,6 +36,25 @@ Options:
3536
-h Show this help message and exit.
3637
`
3738

39+
var supportedFormats = []string{"txt", "pcap", "pcapng"}
40+
41+
type ExtFlag []string
42+
43+
func (f *ExtFlag) MarshalText() ([]byte, error) {
44+
return nil, nil
45+
}
46+
47+
func (f *ExtFlag) UnmarshalText(b []byte) error {
48+
exts := *f
49+
for _, ext := range strings.Split(string(b), ",") {
50+
if !slices.Contains(exts, ext) && slices.Contains(supportedFormats, ext) {
51+
exts = append(exts, ext)
52+
}
53+
}
54+
*f = exts
55+
return nil
56+
}
57+
3858
func displayInterfaces() error {
3959
w := new(tabwriter.Writer)
4060
w.Init(os.Stdout, 0, 0, 2, ' ', tabwriter.TabIndent)
@@ -72,7 +92,6 @@ func root(args []string) error {
7292
flags.DurationVar(&conf.Timeout, "t", 0, "The maximum duration of the packet capture process. Example: 5s")
7393
flags.IntVar(&conf.PacketCount, "c", 0, "The maximum number of packets to capture.")
7494
flags.StringVar(&conf.Expr, "e", "", `BPF filter expression. Example: "ip proto tcp"`)
75-
ext := flags.String("f", "", "File extension to write captured packet data to. Supported values: txt, pcap, pcapng")
7695
flags.BoolFunc("D", "Display list of interfaces and exit.", func(flagValue string) error {
7796
if err := displayInterfaces(); err != nil {
7897
fmt.Fprintf(os.Stderr, "mshark: %v\n", err)
@@ -81,6 +100,8 @@ func root(args []string) error {
81100
os.Exit(0)
82101
return nil
83102
})
103+
exts := ExtFlag([]string{})
104+
flags.TextVar(&exts, "f", &exts, "File extension(s) to write captured data. Supported formats: txt, pcap, pcapng")
84105

85106
flags.Usage = func() {
86107
fmt.Print(usagePrefix)
@@ -104,54 +125,58 @@ func root(args []string) error {
104125
}
105126
conf.Snaplen = *snaplen
106127

107-
// creating writers depending on a file extension
108-
var pw ms.PacketWriter
109-
if *ext != "" {
110-
switch *ext {
111-
case "txt":
112-
f, err := createFile(*ext)
113-
if err != nil {
114-
return err
128+
// creating writers and writing headers depending on a file extension
129+
var pw []ms.PacketWriter
130+
if len(exts) != 0 {
131+
for _, ext := range exts {
132+
switch ext {
133+
case "txt":
134+
f, err := createFile(ext)
135+
if err != nil {
136+
return err
137+
}
138+
defer f.Close()
139+
w := ms.NewWriter(f)
140+
if err := w.WriteHeader(&conf); err != nil {
141+
return err
142+
}
143+
pw = append(pw, w)
144+
case "pcap":
145+
f, err := createFile(ext)
146+
if err != nil {
147+
return err
148+
}
149+
defer f.Close()
150+
w := mpcap.NewWriter(f)
151+
if err := w.WriteHeader(conf.Snaplen); err != nil {
152+
return err
153+
}
154+
pw = append(pw, w)
155+
case "pcapng":
156+
f, err := createFile(ext)
157+
if err != nil {
158+
return err
159+
}
160+
defer f.Close()
161+
w := mpcapng.NewWriter(f)
162+
if err := w.WriteHeader("mshark", conf.Device, conf.Expr, conf.Snaplen); err != nil {
163+
return err
164+
}
165+
pw = append(pw, w)
166+
default:
167+
// unreachable
168+
return fmt.Errorf("unsupported file format: %s", ext)
115169
}
116-
defer f.Close()
117-
pw = ms.NewWriter(f)
118-
case "pcap":
119-
f, err := createFile(*ext)
120-
if err != nil {
121-
return err
122-
}
123-
defer f.Close()
124-
pw = mpcap.NewWriter(f)
125-
case "pcapng":
126-
f, err := createFile(*ext)
127-
if err != nil {
128-
return err
129-
}
130-
defer f.Close()
131-
pw = mpcapng.NewWriter(f)
132-
default:
133-
return fmt.Errorf("unsupported file format: %s", *ext)
134170
}
135171
} else {
136-
pw = ms.NewWriter(os.Stdout)
137-
}
138-
139-
// writing headers
140-
switch t := pw.(type) {
141-
case *ms.Writer:
142-
if err := t.WriteHeader(&conf); err != nil {
143-
return err
144-
}
145-
case *mpcap.Writer:
146-
if err := t.WriteHeader(conf.Snaplen); err != nil {
147-
return err
148-
}
149-
case *mpcapng.Writer:
150-
if err := t.WriteHeader("mshark", conf.Device, conf.Expr, conf.Snaplen); err != nil {
172+
w := ms.NewWriter(os.Stdout)
173+
if err := w.WriteHeader(&conf); err != nil {
151174
return err
152175
}
176+
pw = append(pw, w)
153177
}
154-
if err := ms.OpenLive(&conf, pw); err != nil {
178+
179+
if err := ms.OpenLive(&conf, pw...); err != nil {
155180
return err
156181
}
157182
return nil

mshark.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,9 @@ func InterfaceByName(name string) (*net.Interface, error) {
171171
return in, nil
172172
}
173173

174-
func OpenLive(conf *Config, pw PacketWriter) error {
174+
// OpenLive opens a live capture based on the given configuration and writes
175+
// all captured packets to the given PacketWriters.
176+
func OpenLive(conf *Config, pw ...PacketWriter) error {
175177

176178
packetcfg := packet.Config{}
177179

@@ -220,8 +222,10 @@ func OpenLive(conf *Config, pw PacketWriter) error {
220222
} else {
221223
fmt.Printf("- Packets: %d, Drops: %d, Freeze Queue Count: %d\n",
222224
stats.Packets, stats.Drops, stats.FreezeQueueCount)
223-
if w, ok := pw.(*Writer); ok {
224-
fmt.Printf("- Packets Captured: %d\n", w.packets)
225+
for _, w := range pw {
226+
if w, ok := w.(*Writer); ok {
227+
fmt.Fprintf(w.w, "- Packets Captured: %d\n", w.packets)
228+
}
225229
}
226230
}
227231
// close Conn
@@ -245,9 +249,10 @@ func OpenLive(conf *Config, pw PacketWriter) error {
245249
}
246250
return fmt.Errorf("failed to read Ethernet frame: %v", err)
247251
}
248-
249-
if err := pw.WritePacket(time.Now().UTC(), b[:n]); err != nil {
250-
return err
252+
for _, w := range pw {
253+
if err := w.WritePacket(time.Now().UTC(), b[:n]); err != nil {
254+
return err
255+
}
251256
}
252257
}
253258
return nil

0 commit comments

Comments
 (0)