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+
3858func 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
0 commit comments