captured: directly call NextPacket() to prevent hanging reads
Using Packets() spawns off a separate goroutine which calls NextPacket in a loop until io.EOF is returned. This goroutine will stick around after Close() returned, resulting in only the first wireshark connection working.
This commit is contained in:
parent
d9f5d95812
commit
7d278289f0
@ -20,6 +20,7 @@ import (
|
|||||||
"container/ring"
|
"container/ring"
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
@ -47,17 +48,22 @@ func capturePackets(ctx context.Context) (chan gopacket.Packet, error) {
|
|||||||
for _, ifname := range []string{"uplink0", "lan0"} {
|
for _, ifname := range []string{"uplink0", "lan0"} {
|
||||||
handle, err := pcapgo.NewEthernetHandle(ifname)
|
handle, err := pcapgo.NewEthernetHandle(ifname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("pcapgo.NewEthernetHandle(%v): %v", ifname, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := handle.SetBPF(instructions); err != nil {
|
if err := handle.SetBPF(instructions); err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("SetBPF: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pkgsrc := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet)
|
pkgsrc := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet)
|
||||||
go func() {
|
go func() {
|
||||||
defer handle.Close()
|
defer handle.Close()
|
||||||
for packet := range pkgsrc.Packets() {
|
for {
|
||||||
|
packet, err := pkgsrc.NextPacket()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("NextPacket: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case packets <- packet:
|
case packets <- packet:
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
@ -61,20 +61,25 @@ type session struct {
|
|||||||
channel ssh.Channel
|
channel ssh.Channel
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *session) request(req *ssh.Request, prb *packetRingBuffer) error {
|
func (s *session) request(req *ssh.Request, prb *packetRingBuffer) (err error) {
|
||||||
switch req.Type {
|
switch req.Type {
|
||||||
case "exec":
|
case "exec":
|
||||||
if got, want := len(req.Payload), 4; got < want {
|
if got, want := len(req.Payload), 4; got < want {
|
||||||
return fmt.Errorf("exec request payload too short: got %d, want >= %d", got, want)
|
return fmt.Errorf("exec request payload too short: got %d, want >= %d", got, want)
|
||||||
}
|
}
|
||||||
log.Printf("exec, wantReply %v, payload %q", req.WantReply, string(req.Payload[4:]))
|
log.Printf("exec, wantReply %v, payload %q", req.WantReply, string(req.Payload[4:]))
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("exec done: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
ctx, canc := context.WithCancel(context.Background())
|
ctx, canc := context.WithCancel(context.Background())
|
||||||
defer canc()
|
defer canc()
|
||||||
|
|
||||||
pcapw := pcapgo.NewWriter(s.channel)
|
pcapw := pcapgo.NewWriter(s.channel)
|
||||||
if err := pcapw.WriteFileHeader(1600, layers.LinkTypeEthernet); err != nil {
|
if err := pcapw.WriteFileHeader(1600, layers.LinkTypeEthernet); err != nil {
|
||||||
return err
|
return fmt.Errorf("pcapw.WriteFileHeader: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
prb.Lock()
|
prb.Lock()
|
||||||
@ -82,7 +87,7 @@ func (s *session) request(req *ssh.Request, prb *packetRingBuffer) error {
|
|||||||
buffered := prb.packetsLocked()
|
buffered := prb.packetsLocked()
|
||||||
prb.Unlock()
|
prb.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("capturePackets: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Reply(true, nil)
|
req.Reply(true, nil)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user