Skip to content

Commit

Permalink
Merge branch 'master' into v23docs
Browse files Browse the repository at this point in the history
  • Loading branch information
gcla committed Jun 19, 2021
2 parents e1fc8ad + 49fa930 commit b88a57e
Show file tree
Hide file tree
Showing 53 changed files with 11,354 additions and 435 deletions.
40 changes: 38 additions & 2 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
],
"imageSize": 72,
"commit": false,
"contributorsPerLine": 8,
"commitConvention": "none",
"contributors": [
{
Expand Down Expand Up @@ -428,7 +429,42 @@
"contributions": [
"bug"
]
},
{
"login": "thordy",
"name": "Thord Setsaas",
"avatar_url": "https://avatars.githubusercontent.com/u/1622278?v=4",
"profile": "https://github.com/thordy",
"contributions": [
"doc"
]
},
{
"login": "deliciouslytyped",
"name": "deliciouslytyped",
"avatar_url": "https://avatars.githubusercontent.com/u/47436522?v=4",
"profile": "https://github.com/deliciouslytyped",
"contributions": [
"bug"
]
},
{
"login": "factorion",
"name": "factorion",
"avatar_url": "https://avatars.githubusercontent.com/u/40322086?v=4",
"profile": "https://github.com/factorion",
"contributions": [
"platform"
]
},
{
"login": "herbygillot",
"name": "Herby Gillot",
"avatar_url": "https://avatars.githubusercontent.com/u/618376?v=4",
"profile": "https://github.com/herbygillot",
"contributions": [
"platform"
]
}
],
"contributorsPerLine": 7
]
}
8 changes: 4 additions & 4 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ jobs:
runs-on: ubuntu-latest
steps:

- name: Set up Go 1.12
uses: actions/setup-go@v1
- name: Set up Go 1.13
uses: actions/setup-go@v2
with:
go-version: 1.12
go-version: 1.13
id: go

- name: Check out code into the Go module directory
uses: actions/checkout@v1
uses: actions/checkout@v2

- name: Get dependencies
run: |
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Makefile
dist/
.vscode/
*~
Expand Down
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ go:
- 1.15.x
- 1.14.x
- 1.13.x
- 1.12.x
notifications:
email: true
before_install:
Expand Down
14 changes: 9 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@

### Added

Termshark's columns can now be changed. Use the minibuffer `columns` command to show the current column
set. Columns can be added, removed or hidden from view. If your Wireshark config is available, termshark can
- Termshark's columns can now be changed via the minibuffer `columns` command. Columns can be added, removed
or hidden from view. If your Wireshark config is available, termshark can
import your Wireshark column configuration. Custom columns can be chosen via a display filter expression.
- The packet structure view now provides a contextual menu with options to
- apply the filter representing the current level of structure as a custom column
- prepare or directly apply the same filter as a display filter
- apply the structure filter as a custom column
- prepare or apply the same filter as a display filter
- A new console-command, "wormhole", allows you to send termshark's current pcap with magic wormhole. Pair
with the tmux plugin tmux-wormhole to open the pcap quickly in Wireshark.
- Added a -w flag - if supplied for a live capture, termshark will write the packets to this capture file.

### Changed

Fixed a bug that caused "And" and "Or" conversation filters to be incorrect if the current display filter is
- Fixed a bug that caused "And" and "Or" conversation filters to be incorrect if the current display filter is
empty.
- Fixed a bug that caused multi-token capture filters to fail.

## [2.2.0] - 2021-01-03
### Added
Expand Down
18 changes: 9 additions & 9 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion assets/statik/statik.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion assets/themes/default-16.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ unused = "Color00"

[light]
button = ["default.white","default.gray3"]
button-focus = ["default.black","default.purple"]
button-focus = ["default.white","default.purple"]
button-selected = ["default.black","default.gray3"]
cmdline = ["default.black","default.yellow"]
cmdline-button = ["default.yellow","default.black"]
Expand Down
2 changes: 1 addition & 1 deletion assets/themes/default-256.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ unused = "#79e11a"

[light]
button = ["default.black","default.white"]
button-focus = ["default.black","default.purple"]
button-focus = ["default.white","default.purple"]
button-selected = ["default.black","default.gray04"]
cmdline = ["default.black","default.yellow"]
cmdline-button = ["default.yellow","default.black"]
Expand Down
2 changes: 1 addition & 1 deletion assets/themes/dracula-256.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ unused = "#79e11a"

[dark]
button = ["dracula.black","dracula.gray3"]
button-focus = ["dracula.white","dracula.magenta"]
button-focus = ["dracula.black","dracula.magenta"]
button-selected = ["dracula.white","dracula.gray3"]
cmdline = ["dracula.black","dracula.yellow"]
cmdline-button = ["dracula.yellow","dracula.black"]
Expand Down
2 changes: 1 addition & 1 deletion assets/themes/solarized-256.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ unused = "#79e11a"

[light]
button = ["solarized.black","solarized.white"]
button-focus = ["solarized.black","solarized.purple"]
button-focus = ["solarized.white","solarized.purple"]
button-selected = ["solarized.black","solarized.gray3"]
cmdline = ["solarized.black","solarized.yellow"]
cmdline-button = ["solarized.yellow","solarized.black"]
Expand Down
2 changes: 1 addition & 1 deletion capinfo/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ func (c *Loader) loadCapinfoAsync(pcapf string, app gowid.IApp, cb ICapinfoCallb
}
}

if state == pcap.Terminated || (cancelledChan == nil && state == pcap.NotStarted) {
if state == pcap.Terminated || (procChan == nil && state == pcap.NotStarted) {
break loop
}
}
Expand Down
3 changes: 2 additions & 1 deletion cli/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ type Tshark struct {
// Termshark's own command line arguments. Used if we don't pass through to tshark.
type Termshark struct {
Ifaces []string `value-name:"<interfaces>" short:"i" description:"Interface(s) to read."`
Pcap flags.Filename `value-name:"<file/fifo>" short:"r" description:"Pcap file/fifo to read. Use - for stdin."`
Pcap flags.Filename `value-name:"<infile/fifo>" short:"r" description:"Pcap file/fifo to read. Use - for stdin."`
WriteTo flags.Filename `value-name:"<outfile>" short:"w" description:"Write raw packet data to outfile."`
DecodeAs []string `short:"d" description:"Specify dissection of layer type." value-name:"<layer type>==<selector>,<decode-as protocol>"`
PrintIfaces bool `short:"D" optional:"true" optional-value:"true" description:"Print a list of the interfaces on which termshark can capture."`
DisplayFilter string `short:"Y" description:"Apply display filter." value-name:"<displaY filter>"`
Expand Down
94 changes: 81 additions & 13 deletions cmd/termshark/termshark.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ import (
"github.com/gcla/termshark/v2/cli"
"github.com/gcla/termshark/v2/convs"
"github.com/gcla/termshark/v2/pcap"
"github.com/gcla/termshark/v2/shark"
"github.com/gcla/termshark/v2/streams"
"github.com/gcla/termshark/v2/system"
"github.com/gcla/termshark/v2/theme"
"github.com/gcla/termshark/v2/tty"
"github.com/gcla/termshark/v2/ui"
"github.com/gcla/termshark/v2/widgets/filter"
"github.com/gcla/termshark/v2/widgets/wormhole"
"github.com/gdamore/tcell"
flags "github.com/jessevdk/go-flags"
"github.com/mattn/go-isatty"
Expand Down Expand Up @@ -58,6 +60,7 @@ func main() {
capinfo.Goroutinewg = &ensureGoroutinesStopWG
convs.Goroutinewg = &ensureGoroutinesStopWG
ui.Goroutinewg = &ensureGoroutinesStopWG
wormhole.Goroutinewg = &ensureGoroutinesStopWG

res := cmain()
ensureGoroutinesStopWG.Wait()
Expand Down Expand Up @@ -96,16 +99,16 @@ func cmain() int {
stdConf := configdir.New("", "termshark")
dirs := stdConf.QueryFolders(configdir.Cache)
if err := dirs[0].CreateParentDir("dummy"); err != nil {
fmt.Printf("Warning: could not create cache dir: %v\n", err)
fmt.Fprintf(os.Stderr, "Warning: could not create cache dir: %v\n", err)
}
dirs = stdConf.QueryFolders(configdir.Global)
if err := dirs[0].CreateParentDir("dummy"); err != nil {
fmt.Printf("Warning: could not create config dir: %v\n", err)
fmt.Fprintf(os.Stderr, "Warning: could not create config dir: %v\n", err)
}
viper.AddConfigPath(dirs[0].Path)

if f, err := os.OpenFile(filepath.Join(dirs[0].Path, "termshark.toml"), os.O_RDONLY|os.O_CREATE, 0666); err != nil {
fmt.Printf("Warning: could not create initial config file: %v\n", err)
fmt.Fprintf(os.Stderr, "Warning: could not create initial config file: %v\n", err)
} else {
f.Close()
}
Expand Down Expand Up @@ -147,6 +150,8 @@ func cmain() int {
}
}

// On Windows, termshark itself is used to tail the pcap generated by dumpcap, and the output
// is fed into tshark -T psml ...
if tsopts.TailFileValue() != "" {
err = termshark.TailFile(tsopts.TailFileValue())
if err != nil {
Expand Down Expand Up @@ -418,6 +423,7 @@ func cmain() int {

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

// Work out capture filter afterwards because we need to determine first
Expand All @@ -434,6 +440,22 @@ func cmain() int {
captureFilter = argsFilter
}

// -w something
if opts.WriteTo != "" {
if len(fileSrcs) > 0 {
fmt.Fprintf(os.Stderr, "The -w flag is incompatible with regular capture sources %v\n", fileSrcs)
return 1
}
if opts.WriteTo == "-" {
fmt.Fprintf(os.Stderr, "Cannot set -w to stdout. Target file must be regular or a symlink.\n")
return 1
}
if !system.FileRegularOrLink(string(opts.WriteTo)) {
fmt.Fprintf(os.Stderr, "Cannot set -w to %s. Target file must be regular or a symlink.\n", opts.WriteTo)
return 1
}
}

displayFilter := opts.DisplayFilter

// Validate supplied filters e.g. no capture filter when reading from file
Expand Down Expand Up @@ -482,7 +504,7 @@ func cmain() int {
}()
}

for _, dir := range []string{termshark.CacheDir(), termshark.PcapDir()} {
for _, dir := range []string{termshark.CacheDir(), termshark.DefaultPcapDir(), termshark.PcapDir()} {
if _, err = os.Stat(dir); os.IsNotExist(err) {
err = os.Mkdir(dir, 0777)
if err != nil {
Expand Down Expand Up @@ -640,8 +662,8 @@ 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(pcap.FileSystemSources(psrcs)) == 0 && startedSuccessfully {
fmt.Printf("Packets read from %s have been saved in %s\n", pcap.SourcesString(psrcs), ifacePcapFilename)
if len(pcap.FileSystemSources(psrcs)) == 0 && startedSuccessfully && !ui.WriteToSelected && !ui.WriteToDeleted {
fmt.Fprintf(os.Stderr, "Packets read from %s have been saved in %s\n", pcap.SourcesString(psrcs), ifacePcapFilename)
}
}()

Expand Down Expand Up @@ -693,15 +715,21 @@ func cmain() int {
}

var ifaceTmpFile string
var waitingForPackets bool

// no file sources - so interface or fifo
if len(pcap.FileSystemSources(psrcs)) == 0 {
srcNames := make([]string, 0, len(psrcs))
for _, psrc := range psrcs {
srcNames = append(srcNames, psrc.Name())
if opts.WriteTo != "" {
ifaceTmpFile = string(opts.WriteTo)
ui.WriteToSelected = true
} else {
srcNames := make([]string, 0, len(psrcs))
for _, psrc := range psrcs {
srcNames = append(srcNames, psrc.Name())
}
ifaceTmpFile = pcap.TempPcapFile(srcNames...)
}
ifaceTmpFile = pcap.TempPcapFile(srcNames...)

fmt.Printf("(The termshark UI will start when packets are detected...)\n")
waitingForPackets = true
} else {
// Start UI right away, reading from a file
close(ui.StartUIChan)
Expand Down Expand Up @@ -799,6 +827,23 @@ func cmain() int {
},
}

// Do this before the load starts, so that the PSML process has a guaranteed safe
// PSML column format to use when it begins. The call to RequestLoadPcapWithCheck,
// for example, will access the setting for preferred PSML columns.
//
// Init a global variable with the list of all valid tshark columns and
// their formats. This might start a tshark process if the data isn't
// cached. If so, print a message to console - "initializing". I'm not doing
// anything smarter or async - it's not worth it, this should take a fraction
// of a second.
err = shark.InitValidColumns()

// If this message is needed, we want it to appear after the init message for the packet
// columns - after InitValidColumns
if waitingForPackets {
fmt.Fprintf(os.Stderr, "(The termshark UI will start when packets are detected...)\n")
}

// Refresh
fileSrcs = pcap.FileSystemSources(psrcs)
if len(fileSrcs) > 0 {
Expand All @@ -813,7 +858,7 @@ func cmain() int {
app.Run(gowid.RunFunction(func(app gowid.IApp) {
ui.FilterWidget.SetValue(displayFilter, app)
}))
ui.RequestLoadPcapWithCheck(absfile, displayFilter, ui.NoGlobalJump, app)
ui.RequestLoadPcap(absfile, displayFilter, ui.NoGlobalJump, app)
}
validator.Valid = &filter.ValidateCB{Fn: doit, App: app}
validator.Validate(displayFilter)
Expand Down Expand Up @@ -877,11 +922,16 @@ func cmain() int {

var progCancelTimer *time.Timer

checkedPcapCache := false
checkPcapCacheDuration := 5 * time.Second
checkPcapCacheTimer := time.NewTimer(checkPcapCacheDuration)

Loop:
for {
var finChan <-chan time.Time
var tickChan <-chan time.Time
var inactivityChan <-chan time.Time
var checkPcapCacheChan <-chan time.Time
var tcellEvents <-chan tcell.Event
var opsChan <-chan gowid.RunFunction
var afterRenderEvents <-chan gowid.IAfterRenderEvent
Expand Down Expand Up @@ -948,6 +998,10 @@ Loop:
inactivityChan = inactivityTimer.C
}

if !checkedPcapCache {
checkPcapCacheChan = checkPcapCacheTimer.C
}

// Only process tcell and gowid events if the UI is running.
if ui.Running {
tcellEvents = app.TCellEvents
Expand All @@ -973,6 +1027,16 @@ Loop:

select {

case <-checkPcapCacheChan:
// Only check the cache dir if we own it; don't want to delete pcap files
// that might be shared with wireshark
if termshark.ConfBool("main.use-tshark-temp-for-pcap-cache", false) {
log.Infof("Termshark does not own the pcap temp dir %s; skipping size check", termshark.PcapDir())
} else {
termshark.PrunePcapCache()
}
checkedPcapCache = true

case <-inactivityChan:
ui.Fin.Activate()
app.Redraw()
Expand Down Expand Up @@ -1053,6 +1117,9 @@ Loop:
// will happen next time round because the quitRequested flag is checked.
stopLoaders()
}
if ui.CurrentWormholeWidget != nil {
ui.CurrentWormholeWidget.Close()
}

case sig := <-sigChan:
if system.IsSigTSTP(sig) {
Expand Down Expand Up @@ -1168,6 +1235,7 @@ Loop:
case ev := <-tcellEvents:
app.HandleTCellEvent(ev, gowid.IgnoreUnhandledInput)
inactivityTimer.Reset(inactiveDuration)
checkPcapCacheTimer.Reset(checkPcapCacheDuration)

case ev, ok := <-afterRenderEvents:
// This means app.Quit() has been called, which closes the AfterRenderEvents
Expand Down
Loading

0 comments on commit b88a57e

Please sign in to comment.