Skip to content

Commit

Permalink
Fifo support was broken - this is a fix
Browse files Browse the repository at this point in the history
Now I hope that commands like these work again:

cat foo.pcap > fifo &
termshark -r fifo

Test cases coming up next to ensure they continue to work!
  • Loading branch information
gcla committed Jun 28, 2020
1 parent fea0326 commit e8f9435
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 54 deletions.
109 changes: 56 additions & 53 deletions cmd/termshark/termshark.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,63 +345,14 @@ func cmain() int {
}
}

fileSrcs := pcap.FileSystemSources(psrcs)
if len(fileSrcs) == 1 {
if len(psrcs) > 1 {
fmt.Fprintf(os.Stderr, "You can't specify both a pcap and a live capture.\n")
return 1
}
} else if len(fileSrcs) > 1 {
fmt.Fprintf(os.Stderr, "You can't specify more than one pcap.\n")
return 1
}

// Invariant: len(psrcs) > 0
// Invariant: len(fileSrcs) == 1 => len(psrcs) == 1

// go-flags returns [""] when no extra args are provided, so I can't just
// test the length of this slice
argsFilter := strings.Join(filterArgs, " ")

// Work out capture filter afterwards because we need to determine first
// whether any potential first argument is intended as a pcap file instead of
// a capture filter.
captureFilter := opts.CaptureFilter

// Meaning there are only live captures
if len(fileSrcs) == 0 && argsFilter != "" {
if opts.CaptureFilter != "" {
fmt.Fprintf(os.Stderr, "Two capture filters provided - '%s' and '%s' - please supply one only.\n", opts.CaptureFilter, argsFilter)
return 1
}
captureFilter = argsFilter
}

displayFilter := opts.DisplayFilter

// Validate supplied filters e.g. no capture filter when reading from file
if len(fileSrcs) > 0 {
if captureFilter != "" {
fmt.Fprintf(os.Stderr, "Cannot use a capture filter when reading from a pcap file - '%s' and '%s'.\n", captureFilter, pcapf)
return 1
}
if argsFilter != "" {
if opts.DisplayFilter != "" {
fmt.Fprintf(os.Stderr, "Two display filters provided - '%s' and '%s' - please supply one only.\n", opts.DisplayFilter, argsFilter)
return 1
}
displayFilter = argsFilter
}
}

// - means read from stdin. But termshark uses stdin for interacting with the UI. So if the
// iface is -, then dup stdin to a free descriptor, adjust iface to read from that descriptor,
// then open /dev/tty on stdin.
newinputfd := -1

// Here we check for
// (a) sources named '-' - these need rewritten to /dev/fd/N and stdin needs to be moved
// (b) fifo sources
// (b) fifo sources - these are switched from -r to -i because that's what tshark needs
renamedStdin := false
for pi, psrc := range psrcs {
switch {
Expand Down Expand Up @@ -430,7 +381,7 @@ func cmain() int {
default:
stat, err := os.Stat(psrc.Name())
if err != nil {
if len(fileSrcs) > 0 {
if psrc.IsFile() || psrc.IsFifo() {
// Means this was supplied with -r - since any file sources means there's (a) 1 and (b)
// no other sources. So it must stat. Note if we started with -i fifo, this check
// isn't done... but it still ought to exist.
Expand Down Expand Up @@ -458,6 +409,56 @@ func cmain() int {
}
}

// Means files
fileSrcs := pcap.FileSystemSources(psrcs)
if len(fileSrcs) == 1 {
if len(psrcs) > 1 {
fmt.Fprintf(os.Stderr, "You can't specify both a pcap and a live capture.\n")
return 1
}
} else if len(fileSrcs) > 1 {
fmt.Fprintf(os.Stderr, "You can't specify more than one pcap.\n")
return 1
}

// Invariant: len(psrcs) > 0
// Invariant: len(fileSrcs) == 1 => len(psrcs) == 1

// go-flags returns [""] when no extra args are provided, so I can't just
// test the length of this slice
argsFilter := strings.Join(filterArgs, " ")

// Work out capture filter afterwards because we need to determine first
// whether any potential first argument is intended as a pcap file instead of
// a capture filter.
captureFilter := opts.CaptureFilter

// Meaning there are only live captures
if len(fileSrcs) == 0 && argsFilter != "" {
if opts.CaptureFilter != "" {
fmt.Fprintf(os.Stderr, "Two capture filters provided - '%s' and '%s' - please supply one only.\n", opts.CaptureFilter, argsFilter)
return 1
}
captureFilter = argsFilter
}

displayFilter := opts.DisplayFilter

// Validate supplied filters e.g. no capture filter when reading from file
if len(fileSrcs) > 0 {
if captureFilter != "" {
fmt.Fprintf(os.Stderr, "Cannot use a capture filter when reading from a pcap file - '%s' and '%s'.\n", captureFilter, pcapf)
return 1
}
if argsFilter != "" {
if opts.DisplayFilter != "" {
fmt.Fprintf(os.Stderr, "Two display filters provided - '%s' and '%s' - please supply one only.\n", opts.DisplayFilter, argsFilter)
return 1
}
displayFilter = argsFilter
}
}

// Here we now have an accurate view of all psrcs - either file, fifo, pipe or interface

// Helpful to use logging when enumerating interfaces below, so do it first
Expand Down Expand Up @@ -642,7 +643,7 @@ func cmain() int {
// fifo. In all cases, we save the packets to a file so that if a
// filter is applied, we can restart - and so that we preserve the
// capture at the end of running termshark.
if len(fileSrcs) == 0 && startedSuccessfully {
if len(pcap.FileSystemSources(psrcs)) == 0 && startedSuccessfully {
fmt.Printf("Packets read from %s have been saved in %s\n", pcap.SourcesString(psrcs), ifacePcapFilename)
}
}()
Expand Down Expand Up @@ -710,7 +711,7 @@ func cmain() int {
var iwatcher *fsnotify.Watcher
var ifaceTmpFile string

if len(fileSrcs) == 0 {
if len(pcap.FileSystemSources(psrcs)) == 0 {
srcNames := make([]string, 0, len(psrcs))
for _, psrc := range psrcs {
srcNames = append(srcNames, psrc.Name())
Expand Down Expand Up @@ -793,6 +794,8 @@ func cmain() int {
},
}

// Refresh
fileSrcs = pcap.FileSystemSources(psrcs)
if len(fileSrcs) > 0 {
psrc := fileSrcs[0]
absfile, err := filepath.Abs(psrc.Name())
Expand Down
23 changes: 22 additions & 1 deletion pcap/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package pcap

import (
"fmt"
"os"
"strings"

Expand All @@ -26,7 +27,7 @@ type IPacketSource interface {
func FileSystemSources(srcs []IPacketSource) []IPacketSource {
res := make([]IPacketSource, 0)
for _, src := range srcs {
if src.IsFile() || src.IsFifo() {
if src.IsFile() {
res = append(res, src)
}
}
Expand Down Expand Up @@ -85,6 +86,10 @@ func (p FileSource) IsPipe() bool {
return false
}

func (p FileSource) String() string {
return fmt.Sprintf("File:%s", p.Filename)
}

//======================================================================

type TemporaryFileSource struct {
Expand All @@ -99,6 +104,10 @@ func (p TemporaryFileSource) Remove() error {
return os.Remove(p.Filename)
}

func (p TemporaryFileSource) String() string {
return fmt.Sprintf("TempFile:%s", p.Filename)
}

//======================================================================

type InterfaceSource struct {
Expand Down Expand Up @@ -127,6 +136,10 @@ func (p InterfaceSource) IsPipe() bool {
return false
}

func (p InterfaceSource) String() string {
return fmt.Sprintf("Interface:%s", p.Iface)
}

//======================================================================

type FifoSource struct {
Expand Down Expand Up @@ -155,6 +168,10 @@ func (p FifoSource) IsPipe() bool {
return false
}

func (p FifoSource) String() string {
return fmt.Sprintf("Fifo:%s", p.Filename)
}

//======================================================================

type PipeSource struct {
Expand Down Expand Up @@ -189,6 +206,10 @@ func (p PipeSource) Close() error {
return nil
}

func (p PipeSource) String() string {
return fmt.Sprintf("Pipe:%s(%d)", p.Descriptor, p.Fd)
}

//======================================================================
// Local Variables:
// mode: Go
Expand Down

0 comments on commit e8f9435

Please sign in to comment.