Skip to content

Commit

Permalink
Merge pull request #115 from ddddddO/save_pcap
Browse files Browse the repository at this point in the history
Save pcap
  • Loading branch information
ddddddO authored Feb 23, 2025
2 parents b75f37e + aa47b81 commit 9daf78c
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 7 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
packemon_pcap/
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Packemon's Monitor allows user to select each packet by pressing `Enter` key. Th
> Incidentally, dropping RST packets is done by running [the eBPF program](./egress_control/).
> The background note incorporating the eBPF is the POST of X around [here](https://x.com/ddddddOpppppp/status/1798715056513056881).
- [x] Send generated packets to any network interfaces.
- Send generated packets to any network interfaces.
- You can specify network interface with `--interface` flag. Default is `eth0`.

- The following types of packets are covered.
Expand Down Expand Up @@ -70,9 +70,11 @@ Packemon's Monitor allows user to select each packet by pressing `Enter` key. Th

### Packet Monitor

- [x] Monitor any network interfaces.
- Monitor any network interfaces.
- You can specify network interface with `--interface` flag. Default is `eth0`.

- Specified packets can be saved to pcap file.

- The following types of packets are covered.
- [x] Ethernet
- [x] ARP
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ require (
github.com/gdamore/encoding v1.0.1 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/gopacket/gopacket v1.3.1 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/gopacket/gopacket v1.3.1 h1:ZppWyLrOJNZPe5XkdjLbtuTkfQoxQ0xyMJzQCqtqaPU=
github.com/gopacket/gopacket v1.3.1/go.mod h1:3I13qcqSpB2R9fFQg866OOgzylYkZxLTmkvcXhvf6qg=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
Expand Down
2 changes: 1 addition & 1 deletion internal/tui/tui.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,5 @@ func (t *tui) Monitor(passiveCh <-chan *packemon.Passive, columns string) error
})

go t.updateTable(passiveCh, columns)
return t.app.SetRoot(t.pages, true).Run()
return t.app.SetRoot(t.pages, true).EnableMouse(true).Run()
}
82 changes: 78 additions & 4 deletions internal/tui/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ package tui

import (
"fmt"
"os"
"path/filepath"
"runtime/debug"
"strings"
"time"

"github.com/ddddddO/packemon"
"github.com/gdamore/tcell/v2"
"github.com/gopacket/gopacket"
"github.com/gopacket/gopacket/layers"
"github.com/gopacket/gopacket/pcapgo"
"github.com/rivo/tview"
)

Expand All @@ -30,22 +36,35 @@ func (t *tui) updateView(passive *packemon.Passive) {
t.grid.Clear()
})

rows := make([]int, len(viewers))
columns := make([]int, len(viewers))
t.grid.RemoveItem(t.grid) // ほんと?

// +1 分は、PCAP保存領域用(savingPCAPView)
rows := make([]int, len(viewers)+1)
columns := make([]int, len(viewers)+1)
rows[0] = 5
columns[0] = 30
for i := range viewers {
rows[i] = viewers[i].rows()
columns[i] = viewers[i].columns()
}
t.grid.RemoveItem(t.grid) // ほんと?
t.grid.SetRows(rows...).SetColumns(columns...).SetBorders(false)

// SetRows しなくなったので、各テーブルの rows メソッドいらないかも
// t.grid.SetRows(rows...).SetColumns(columns...).SetBorders(false)
t.grid.SetColumns(columns...).SetBorders(false)

for i := range viewers {
t.grid.AddItem(viewers[i].viewTable(), i, 0, 1, 3, 0, 0, false) // focus=true にするとスクロールしない
}
savingPCAPView := t.savingPCAPView(passive)
row := len(viewers)
t.grid.AddItem(savingPCAPView, row, 0, 1, 3, 0, 0, false)

t.grid.SetInputCapture(
func(event *tcell.EventKey) *tcell.EventKey {
if event.Key() == tcell.KeyEscape {
t.grid.Clear()
t.pages.SwitchToPage("history")
t.app.SetFocus(t.pages)
}
return event
})
Expand Down Expand Up @@ -130,6 +149,61 @@ func passiveToViewers(passive *packemon.Passive) []Viewer {
return viewers
}

func (t *tui) savingPCAPView(p *packemon.Passive) *tview.Form {
now := time.Now()
fpath := fmt.Sprintf("./packemon_pcap/%s.pcap", now.Format("20060102150405"))
form := tview.NewForm().
AddInputField("File Name", fpath, 40, func(textToCheck string, lastChar rune) bool {
if len(textToCheck) < 40 {
fpath = textToCheck
return true
} else if len(textToCheck) > 40 {
return false
}
fpath = textToCheck
return true
}, nil).
AddButton("Save", func() {
if p.EthernetFrame == nil {
t.addErrPageForMonitor(fmt.Errorf("Empty ethernet frame..."))
return
}

dir := filepath.Dir(fpath)
if err := os.MkdirAll(dir, 0755); err != nil {
t.addErrPageForMonitor(err)
return
}

f, err := os.Create(fpath)
if err != nil {
t.addErrPageForMonitor(err)
return
}
defer f.Close()

pcapw := pcapgo.NewWriter(f)
if err := pcapw.WriteFileHeader(1500, layers.LinkTypeEthernet); err != nil {
t.addErrPageForMonitor(err)
return
}
ci := gopacket.CaptureInfo{
Timestamp: now,
CaptureLength: 1500,
Length: 1500,
// InterfaceIndex: intf.Index, // 必須ではなさそう
}
if err := pcapw.WritePacket(ci, p.EthernetFrame.Bytes()); err != nil {
t.addErrPageForMonitor(err)
return
}
})
form.SetBorder(true)
form.Box = tview.NewBox().SetBorder(true).SetTitle(" Save PACP ").SetTitleAlign(tview.AlignLeft).SetBorderPadding(1, 1, 1, 1)

return form
}

func tableCellTitle(title string) *tview.TableCell {
return tview.NewTableCell(padding(title))
}
Expand Down

0 comments on commit 9daf78c

Please sign in to comment.