mirror of
https://github.com/bettercap/bettercap
synced 2025-08-19 13:09:49 -07:00
fix: fixed a bug in the gatt library which prevented ble.recon/ble.enum to work multiple times (fixes #471)
This commit is contained in:
parent
f68957b769
commit
120db4db3d
7 changed files with 75 additions and 13 deletions
4
Gopkg.lock
generated
4
Gopkg.lock
generated
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:c309b41787813f80ec393023471014b0be16346bba6e16bf5fa01ce1d310a4ea"
|
digest = "1:a2c142e6c2aa1c71796c748bbe42d224e23d6638fd5b3ae153e70a4b08a8da4e"
|
||||||
name = "github.com/bettercap/gatt"
|
name = "github.com/bettercap/gatt"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
"xpc",
|
"xpc",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "1353e80bee488dc02d1f7e42759c1352492bf18b"
|
revision = "277ee0d0ef94d26e3190252c59fa34dde0df4f26"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
|
|
@ -6,7 +6,6 @@ package ble
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
golog "log"
|
golog "log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -15,6 +14,8 @@ import (
|
||||||
"github.com/bettercap/bettercap/session"
|
"github.com/bettercap/bettercap/session"
|
||||||
|
|
||||||
"github.com/bettercap/gatt"
|
"github.com/bettercap/gatt"
|
||||||
|
|
||||||
|
"github.com/evilsocket/islazy/str"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BLERecon struct {
|
type BLERecon struct {
|
||||||
|
@ -126,15 +127,25 @@ func (mod *BLERecon) isEnumerating() bool {
|
||||||
return mod.currDevice != nil
|
return mod.currDevice != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type dummyWriter struct {
|
||||||
|
mod *BLERecon
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w dummyWriter) Write(p []byte) (n int, err error) {
|
||||||
|
w.mod.Debug("[gatt.log] %s", str.Trim(string(p)))
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (mod *BLERecon) Configure() (err error) {
|
func (mod *BLERecon) Configure() (err error) {
|
||||||
if mod.Running() {
|
if mod.Running() {
|
||||||
return session.ErrAlreadyStarted
|
return session.ErrAlreadyStarted
|
||||||
} else if mod.gattDevice == nil {
|
} else if mod.gattDevice == nil {
|
||||||
mod.Debug("initializing device ...")
|
mod.Debug("initializing device ...")
|
||||||
|
|
||||||
// hey Paypal GATT library, could you please just STFU?!
|
golog.SetFlags(0)
|
||||||
golog.SetOutput(ioutil.Discard)
|
golog.SetOutput(dummyWriter{mod})
|
||||||
if mod.gattDevice, err = gatt.NewDevice(defaultBLEClientOptions...); err != nil {
|
if mod.gattDevice, err = gatt.NewDevice(defaultBLEClientOptions...); err != nil {
|
||||||
|
mod.Debug("error while creating new gatt device: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +173,17 @@ func (mod *BLERecon) Start() error {
|
||||||
|
|
||||||
mod.Info("stopping scan ...")
|
mod.Info("stopping scan ...")
|
||||||
|
|
||||||
mod.gattDevice.StopScanning()
|
if mod.currDevice != nil && mod.currDevice.Device != nil && mod.gattDevice != nil {
|
||||||
|
mod.Debug("resetting connection with %v", mod.currDevice.Device)
|
||||||
|
mod.gattDevice.CancelConnection(mod.currDevice.Device)
|
||||||
|
}
|
||||||
|
|
||||||
|
mod.Debug("stopping device")
|
||||||
|
if err := mod.gattDevice.Stop(); err != nil {
|
||||||
|
mod.Warning("error while stopping device: %v", err)
|
||||||
|
} else {
|
||||||
|
mod.Debug("gatt device closed")
|
||||||
|
}
|
||||||
|
|
||||||
mod.done <- true
|
mod.done <- true
|
||||||
})
|
})
|
||||||
|
@ -172,6 +193,9 @@ func (mod *BLERecon) Stop() error {
|
||||||
return mod.SetRunning(false, func() {
|
return mod.SetRunning(false, func() {
|
||||||
mod.quit <- true
|
mod.quit <- true
|
||||||
<-mod.done
|
<-mod.done
|
||||||
|
mod.Debug("module stopped, cleaning state")
|
||||||
|
mod.gattDevice = nil
|
||||||
|
mod.setCurrentDevice(nil)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,12 @@ func (mod *BLERecon) onStateChanged(dev gatt.Device, s gatt.State) {
|
||||||
if mod.currDevice == nil {
|
if mod.currDevice == nil {
|
||||||
mod.Info("starting discovery ...")
|
mod.Info("starting discovery ...")
|
||||||
dev.Scan([]gatt.UUID{}, true)
|
dev.Scan([]gatt.UUID{}, true)
|
||||||
|
} else {
|
||||||
|
mod.Debug("current device was not cleaned: %v", mod.currDevice)
|
||||||
}
|
}
|
||||||
case gatt.StatePoweredOff:
|
case gatt.StatePoweredOff:
|
||||||
|
mod.Debug("resetting device instance")
|
||||||
|
mod.gattDevice.StopScanning()
|
||||||
mod.setCurrentDevice(nil)
|
mod.setCurrentDevice(nil)
|
||||||
mod.gattDevice = nil
|
mod.gattDevice = nil
|
||||||
|
|
||||||
|
@ -51,6 +55,7 @@ func (mod *BLERecon) onPeriphConnected(p gatt.Peripheral, err error) {
|
||||||
defer func(per gatt.Peripheral) {
|
defer func(per gatt.Peripheral) {
|
||||||
mod.Info("disconnecting from %s ...", per.ID())
|
mod.Info("disconnecting from %s ...", per.ID())
|
||||||
per.Device().CancelConnection(per)
|
per.Device().CancelConnection(per)
|
||||||
|
mod.setCurrentDevice(nil)
|
||||||
}(p)
|
}(p)
|
||||||
|
|
||||||
mod.Session.Events.Add("ble.device.connected", mod.currDevice)
|
mod.Session.Events.Add("ble.device.connected", mod.currDevice)
|
||||||
|
|
8
vendor/github.com/bettercap/gatt/linux/device.go
generated
vendored
8
vendor/github.com/bettercap/gatt/linux/device.go
generated
vendored
|
@ -22,6 +22,7 @@ type device struct {
|
||||||
func newDevice(n int, chk bool) (*device, error) {
|
func newDevice(n int, chk bool) (*device, error) {
|
||||||
fd, err := socket.Socket(socket.AF_BLUETOOTH, syscall.SOCK_RAW, socket.BTPROTO_HCI)
|
fd, err := socket.Socket(socket.AF_BLUETOOTH, syscall.SOCK_RAW, socket.BTPROTO_HCI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("could not create AF_BLUETOOTH raw socket")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if n != -1 {
|
if n != -1 {
|
||||||
|
@ -30,13 +31,17 @@ func newDevice(n int, chk bool) (*device, error) {
|
||||||
|
|
||||||
req := devListRequest{devNum: hciMaxDevices}
|
req := devListRequest{devNum: hciMaxDevices}
|
||||||
if err := gioctl.Ioctl(uintptr(fd), hciGetDeviceList, uintptr(unsafe.Pointer(&req))); err != nil {
|
if err := gioctl.Ioctl(uintptr(fd), hciGetDeviceList, uintptr(unsafe.Pointer(&req))); err != nil {
|
||||||
|
log.Printf("hciGetDeviceList failed")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
log.Printf("got %d devices", req.devNum)
|
||||||
for i := 0; i < int(req.devNum); i++ {
|
for i := 0; i < int(req.devNum); i++ {
|
||||||
d, err := newSocket(fd, i, chk)
|
d, err := newSocket(fd, i, chk)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Printf("dev: %s opened", d.name)
|
log.Printf("dev: %s opened", d.name)
|
||||||
return d, err
|
return d, err
|
||||||
|
} else {
|
||||||
|
log.Printf("error while opening device %d: %v", i, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, errors.New("no supported devices available")
|
return nil, errors.New("no supported devices available")
|
||||||
|
@ -45,6 +50,7 @@ func newDevice(n int, chk bool) (*device, error) {
|
||||||
func newSocket(fd, n int, chk bool) (*device, error) {
|
func newSocket(fd, n int, chk bool) (*device, error) {
|
||||||
i := hciDevInfo{id: uint16(n)}
|
i := hciDevInfo{id: uint16(n)}
|
||||||
if err := gioctl.Ioctl(uintptr(fd), hciGetDeviceInfo, uintptr(unsafe.Pointer(&i))); err != nil {
|
if err := gioctl.Ioctl(uintptr(fd), hciGetDeviceInfo, uintptr(unsafe.Pointer(&i))); err != nil {
|
||||||
|
log.Printf("hciGetDeviceInfo failed")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
name := string(i.name[:])
|
name := string(i.name[:])
|
||||||
|
@ -61,6 +67,7 @@ func newSocket(fd, n int, chk bool) (*device, error) {
|
||||||
}
|
}
|
||||||
log.Printf("dev: %s reset", name)
|
log.Printf("dev: %s reset", name)
|
||||||
if err := gioctl.Ioctl(uintptr(fd), hciResetDevice, uintptr(n)); err != nil {
|
if err := gioctl.Ioctl(uintptr(fd), hciResetDevice, uintptr(n)); err != nil {
|
||||||
|
log.Printf("hciResetDevice failed")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,5 +112,6 @@ func (d device) Write(b []byte) (int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d device) Close() error {
|
func (d device) Close() error {
|
||||||
|
log.Printf("linux.device.Close()")
|
||||||
return syscall.Close(d.fd)
|
return syscall.Close(d.fd)
|
||||||
}
|
}
|
||||||
|
|
35
vendor/github.com/bettercap/gatt/linux/hci.go
generated
vendored
35
vendor/github.com/bettercap/gatt/linux/hci.go
generated
vendored
|
@ -26,7 +26,8 @@ type HCI struct {
|
||||||
bufCnt chan struct{}
|
bufCnt chan struct{}
|
||||||
bufSize int
|
bufSize int
|
||||||
|
|
||||||
pool *util.BytePool
|
pool *util.BytePool
|
||||||
|
loopDone chan bool
|
||||||
|
|
||||||
maxConn int
|
maxConn int
|
||||||
connsmu *sync.Mutex
|
connsmu *sync.Mutex
|
||||||
|
@ -68,7 +69,8 @@ func NewHCI(devID int, chk bool, maxConn int) (*HCI, error) {
|
||||||
bufCnt: make(chan struct{}, 15-1),
|
bufCnt: make(chan struct{}, 15-1),
|
||||||
bufSize: 27,
|
bufSize: 27,
|
||||||
|
|
||||||
pool: util.NewBytePool(4096, 16),
|
pool: util.NewBytePool(4096, 16),
|
||||||
|
loopDone: make(chan bool),
|
||||||
|
|
||||||
maxConn: maxConn,
|
maxConn: maxConn,
|
||||||
connsmu: &sync.Mutex{},
|
connsmu: &sync.Mutex{},
|
||||||
|
@ -89,9 +91,15 @@ func NewHCI(devID int, chk bool, maxConn int) (*HCI, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HCI) Close() error {
|
func (h *HCI) Close() error {
|
||||||
|
log.Printf("hci.Close()")
|
||||||
|
h.pool.Put(nil)
|
||||||
|
<-h.loopDone
|
||||||
|
log.Printf("mainLoop exited")
|
||||||
for _, c := range h.conns {
|
for _, c := range h.conns {
|
||||||
|
log.Printf("closing connection %v", c)
|
||||||
c.Close()
|
c.Close()
|
||||||
}
|
}
|
||||||
|
log.Printf("closing %v", h.d)
|
||||||
return h.d.Close()
|
return h.d.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +159,10 @@ func (h *HCI) Connect(pd *PlatData) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HCI) CancelConnection(pd *PlatData) error {
|
func (h *HCI) CancelConnection(pd *PlatData) error {
|
||||||
return pd.Conn.Close()
|
if pd != nil && pd.Conn != nil {
|
||||||
|
return pd.Conn.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HCI) SendRawCommand(c cmd.CmdParam) ([]byte, error) {
|
func (h *HCI) SendRawCommand(c cmd.CmdParam) ([]byte, error) {
|
||||||
|
@ -166,19 +177,33 @@ func btoi(b bool) uint8 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HCI) mainLoop() {
|
func (h *HCI) mainLoop() {
|
||||||
|
log.Printf("hci.mainLoop started")
|
||||||
|
defer func() {
|
||||||
|
h.loopDone <- true
|
||||||
|
}()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
// log.Printf("hci.mainLoop pool.Get")
|
||||||
b := h.pool.Get()
|
b := h.pool.Get()
|
||||||
|
if b == nil {
|
||||||
|
log.Printf("got nil buffer, breaking mainLoop")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// log.Printf("hci.mainLoop Read(%d)", len(b))
|
||||||
n, err := h.d.Read(b)
|
n, err := h.d.Read(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Sprintf("mainloop err: %v\n", err)
|
log.Printf("mainloop err: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
println("mainLoop failed to read")
|
log.Printf("mainLoop failed to read")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// log.Printf("hci.mainLoop -> handlePacket")
|
||||||
h.handlePacket(b, n)
|
h.handlePacket(b, n)
|
||||||
}
|
}
|
||||||
|
log.Printf("hci.mainLoop stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HCI) handlePacket(buf []byte, n int) {
|
func (h *HCI) handlePacket(buf []byte, n int) {
|
||||||
|
|
2
vendor/github.com/bettercap/gatt/linux/l2cap.go
generated
vendored
2
vendor/github.com/bettercap/gatt/linux/l2cap.go
generated
vendored
|
@ -156,7 +156,7 @@ func (c *conn) Close() error {
|
||||||
defer h.connsmu.Unlock()
|
defer h.connsmu.Unlock()
|
||||||
_, found := h.conns[hh]
|
_, found := h.conns[hh]
|
||||||
if !found {
|
if !found {
|
||||||
// log.Printf("l2conn: 0x%04x already disconnected", hh)
|
log.Printf("l2conn: 0x%04x already disconnected", hh)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err, _ := h.c.Send(cmd.Disconnect{ConnectionHandle: hh, Reason: 0x13}); err != nil {
|
if err, _ := h.c.Send(cmd.Disconnect{ConnectionHandle: hh, Reason: 0x13}); err != nil {
|
||||||
|
|
2
vendor/github.com/bettercap/gatt/peripheral_linux.go
generated
vendored
2
vendor/github.com/bettercap/gatt/peripheral_linux.go
generated
vendored
|
@ -407,7 +407,6 @@ func (p *peripheral) loop() {
|
||||||
if rspOp == attRspFor[reqOp] || (rspOp == attOpError && r[1] == reqOp) {
|
if rspOp == attRspFor[reqOp] || (rspOp == attOpError && r[1] == reqOp) {
|
||||||
req.rspc <- r
|
req.rspc <- r
|
||||||
break
|
break
|
||||||
|
|
||||||
}
|
}
|
||||||
log.Printf("Request 0x%02x got a mismatched response: 0x%02x", reqOp, rspOp)
|
log.Printf("Request 0x%02x got a mismatched response: 0x%02x", reqOp, rspOp)
|
||||||
p.l2c.Write(attErrorRsp(rspOp, 0x0000, AttEcodeReqNotSupp))
|
p.l2c.Write(attErrorRsp(rspOp, 0x0000, AttEcodeReqNotSupp))
|
||||||
|
@ -434,6 +433,7 @@ func (p *peripheral) loop() {
|
||||||
copy(b, buf)
|
copy(b, buf)
|
||||||
|
|
||||||
if (b[0] != attOpHandleNotify) && (b[0] != attOpHandleInd) {
|
if (b[0] != attOpHandleNotify) && (b[0] != attOpHandleInd) {
|
||||||
|
log.Printf("response 0x%x", b[0])
|
||||||
rspc <- b
|
rspc <- b
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue