Skip to content

Commit 9daf78c

Browse files
authored
Merge pull request #115 from ddddddO/save_pcap
Save pcap
2 parents b75f37e + aa47b81 commit 9daf78c

File tree

6 files changed

+87
-7
lines changed

6 files changed

+87
-7
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
packemon_pcap/

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Packemon's Monitor allows user to select each packet by pressing `Enter` key. Th
3535
> Incidentally, dropping RST packets is done by running [the eBPF program](./egress_control/).
3636
> The background note incorporating the eBPF is the POST of X around [here](https://x.com/ddddddOpppppp/status/1798715056513056881).
3737
38-
- [x] Send generated packets to any network interfaces.
38+
- Send generated packets to any network interfaces.
3939
- You can specify network interface with `--interface` flag. Default is `eth0`.
4040

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

7171
### Packet Monitor
7272

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

76+
- Specified packets can be saved to pcap file.
77+
7678
- The following types of packets are covered.
7779
- [x] Ethernet
7880
- [x] ARP

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ require (
2020
github.com/gdamore/encoding v1.0.1 // indirect
2121
github.com/go-playground/locales v0.14.1 // indirect
2222
github.com/go-playground/universal-translator v0.18.1 // indirect
23+
github.com/gopacket/gopacket v1.3.1 // indirect
2324
github.com/leodido/go-urn v1.4.0 // indirect
2425
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
2526
github.com/mattn/go-colorable v0.1.13 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7
1616
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
1717
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
1818
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
19+
github.com/gopacket/gopacket v1.3.1 h1:ZppWyLrOJNZPe5XkdjLbtuTkfQoxQ0xyMJzQCqtqaPU=
20+
github.com/gopacket/gopacket v1.3.1/go.mod h1:3I13qcqSpB2R9fFQg866OOgzylYkZxLTmkvcXhvf6qg=
1921
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
2022
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
2123
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=

internal/tui/tui.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,5 +92,5 @@ func (t *tui) Monitor(passiveCh <-chan *packemon.Passive, columns string) error
9292
})
9393

9494
go t.updateTable(passiveCh, columns)
95-
return t.app.SetRoot(t.pages, true).Run()
95+
return t.app.SetRoot(t.pages, true).EnableMouse(true).Run()
9696
}

internal/tui/view.go

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,17 @@ package tui
22

33
import (
44
"fmt"
5+
"os"
6+
"path/filepath"
57
"runtime/debug"
68
"strings"
9+
"time"
710

811
"github.com/ddddddO/packemon"
912
"github.com/gdamore/tcell/v2"
13+
"github.com/gopacket/gopacket"
14+
"github.com/gopacket/gopacket/layers"
15+
"github.com/gopacket/gopacket/pcapgo"
1016
"github.com/rivo/tview"
1117
)
1218

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

33-
rows := make([]int, len(viewers))
34-
columns := make([]int, len(viewers))
39+
t.grid.RemoveItem(t.grid) // ほんと?
40+
41+
// +1 分は、PCAP保存領域用(savingPCAPView)
42+
rows := make([]int, len(viewers)+1)
43+
columns := make([]int, len(viewers)+1)
44+
rows[0] = 5
45+
columns[0] = 30
3546
for i := range viewers {
3647
rows[i] = viewers[i].rows()
3748
columns[i] = viewers[i].columns()
3849
}
39-
t.grid.RemoveItem(t.grid) // ほんと?
40-
t.grid.SetRows(rows...).SetColumns(columns...).SetBorders(false)
50+
51+
// SetRows しなくなったので、各テーブルの rows メソッドいらないかも
52+
// t.grid.SetRows(rows...).SetColumns(columns...).SetBorders(false)
53+
t.grid.SetColumns(columns...).SetBorders(false)
54+
4155
for i := range viewers {
4256
t.grid.AddItem(viewers[i].viewTable(), i, 0, 1, 3, 0, 0, false) // focus=true にするとスクロールしない
4357
}
58+
savingPCAPView := t.savingPCAPView(passive)
59+
row := len(viewers)
60+
t.grid.AddItem(savingPCAPView, row, 0, 1, 3, 0, 0, false)
61+
4462
t.grid.SetInputCapture(
4563
func(event *tcell.EventKey) *tcell.EventKey {
4664
if event.Key() == tcell.KeyEscape {
4765
t.grid.Clear()
4866
t.pages.SwitchToPage("history")
67+
t.app.SetFocus(t.pages)
4968
}
5069
return event
5170
})
@@ -130,6 +149,61 @@ func passiveToViewers(passive *packemon.Passive) []Viewer {
130149
return viewers
131150
}
132151

152+
func (t *tui) savingPCAPView(p *packemon.Passive) *tview.Form {
153+
now := time.Now()
154+
fpath := fmt.Sprintf("./packemon_pcap/%s.pcap", now.Format("20060102150405"))
155+
form := tview.NewForm().
156+
AddInputField("File Name", fpath, 40, func(textToCheck string, lastChar rune) bool {
157+
if len(textToCheck) < 40 {
158+
fpath = textToCheck
159+
return true
160+
} else if len(textToCheck) > 40 {
161+
return false
162+
}
163+
fpath = textToCheck
164+
return true
165+
}, nil).
166+
AddButton("Save", func() {
167+
if p.EthernetFrame == nil {
168+
t.addErrPageForMonitor(fmt.Errorf("Empty ethernet frame..."))
169+
return
170+
}
171+
172+
dir := filepath.Dir(fpath)
173+
if err := os.MkdirAll(dir, 0755); err != nil {
174+
t.addErrPageForMonitor(err)
175+
return
176+
}
177+
178+
f, err := os.Create(fpath)
179+
if err != nil {
180+
t.addErrPageForMonitor(err)
181+
return
182+
}
183+
defer f.Close()
184+
185+
pcapw := pcapgo.NewWriter(f)
186+
if err := pcapw.WriteFileHeader(1500, layers.LinkTypeEthernet); err != nil {
187+
t.addErrPageForMonitor(err)
188+
return
189+
}
190+
ci := gopacket.CaptureInfo{
191+
Timestamp: now,
192+
CaptureLength: 1500,
193+
Length: 1500,
194+
// InterfaceIndex: intf.Index, // 必須ではなさそう
195+
}
196+
if err := pcapw.WritePacket(ci, p.EthernetFrame.Bytes()); err != nil {
197+
t.addErrPageForMonitor(err)
198+
return
199+
}
200+
})
201+
form.SetBorder(true)
202+
form.Box = tview.NewBox().SetBorder(true).SetTitle(" Save PACP ").SetTitleAlign(tview.AlignLeft).SetBorderPadding(1, 1, 1, 1)
203+
204+
return form
205+
}
206+
133207
func tableCellTitle(title string) *tview.TableCell {
134208
return tview.NewTableCell(padding(title))
135209
}

0 commit comments

Comments
 (0)